From 1e3f7ad9a4ab1cd2de4efd557de768f93ed3e524 Mon Sep 17 00:00:00 2001 From: Tobie Booth Date: Fri, 5 Aug 2016 14:05:43 -0500 Subject: [PATCH 001/193] Return to previous alarm state after trigger (#2580) --- homeassistant/components/alarm_control_panel/manual.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/manual.py b/homeassistant/components/alarm_control_panel/manual.py index 3e904601638..a71edb68ebd 100644 --- a/homeassistant/components/alarm_control_panel/manual.py +++ b/homeassistant/components/alarm_control_panel/manual.py @@ -40,7 +40,7 @@ class ManualAlarm(alarm.AlarmControlPanel): When armed, will be pending for 'pending_time', after that armed. When triggered, will be pending for 'trigger_time'. After that will be - triggered for 'trigger_time', after that we return to disarmed. + triggered for 'trigger_time', after that we return to the previous state. """ def __init__(self, hass, name, code, pending_time, trigger_time): @@ -51,6 +51,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._code = str(code) if code else None self._pending_time = datetime.timedelta(seconds=pending_time) self._trigger_time = datetime.timedelta(seconds=trigger_time) + self._pre_trigger_state = self._state self._state_ts = None @property @@ -77,7 +78,7 @@ class ManualAlarm(alarm.AlarmControlPanel): return STATE_ALARM_PENDING elif (self._state_ts + self._pending_time + self._trigger_time) < dt_util.utcnow(): - return STATE_ALARM_DISARMED + return self._pre_trigger_state return self._state @@ -125,6 +126,7 @@ class ManualAlarm(alarm.AlarmControlPanel): def alarm_trigger(self, code=None): """Send alarm trigger command. No code needed.""" + self._pre_trigger_state = self._state self._state = STATE_ALARM_TRIGGERED self._state_ts = dt_util.utcnow() self.update_ha_state() From abaffc2d8cc692d47cbf882e2102ff81c7e60b13 Mon Sep 17 00:00:00 2001 From: Tobie Booth Date: Sat, 13 Aug 2016 12:48:33 -0500 Subject: [PATCH 002/193] add disarm_after_trigger to manual alarm panel --- .../components/alarm_control_panel/demo.py | 2 +- .../components/alarm_control_panel/manual.py | 44 ++++++++++--- homeassistant/const.py | 6 +- .../alarm_control_panel/test_manual.py | 61 ++++++++++++++++--- 4 files changed, 91 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/demo.py b/homeassistant/components/alarm_control_panel/demo.py index 9ac98924b2b..ccbe3e72e3c 100644 --- a/homeassistant/components/alarm_control_panel/demo.py +++ b/homeassistant/components/alarm_control_panel/demo.py @@ -10,5 +10,5 @@ import homeassistant.components.alarm_control_panel.manual as manual def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Demo alarm control panel platform.""" add_devices([ - manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10), + manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10, False), ]) diff --git a/homeassistant/components/alarm_control_panel/manual.py b/homeassistant/components/alarm_control_panel/manual.py index a71edb68ebd..a95eff20e1f 100644 --- a/homeassistant/components/alarm_control_panel/manual.py +++ b/homeassistant/components/alarm_control_panel/manual.py @@ -7,28 +7,46 @@ https://home-assistant.io/components/alarm_control_panel.manual/ import datetime import logging +import voluptuous as vol + import homeassistant.components.alarm_control_panel as alarm import homeassistant.util.dt as dt_util from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, - STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED) + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, CONF_PLATFORM, CONF_NAME, + CONF_CODE, CONF_PENDING_TIME, CONF_TRIGGER_TIME, CONF_DISARM_AFTER_TRIGGER) +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import track_point_in_time -_LOGGER = logging.getLogger(__name__) - DEFAULT_ALARM_NAME = 'HA Alarm' DEFAULT_PENDING_TIME = 60 DEFAULT_TRIGGER_TIME = 120 +DEFAULT_DISARM_AFTER_TRIGGER = False + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): 'manual', + vol.Optional(CONF_NAME, default=DEFAULT_ALARM_NAME): cv.string, + vol.Optional(CONF_CODE): cv.string, + vol.Optional(CONF_PENDING_TIME, default=DEFAULT_PENDING_TIME): + vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_TRIGGER_TIME, default=DEFAULT_TRIGGER_TIME): + vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_DISARM_AFTER_TRIGGER, + default=DEFAULT_DISARM_AFTER_TRIGGER): cv.boolean, +}) + +_LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the manual alarm platform.""" add_devices([ManualAlarm( hass, - config.get('name', DEFAULT_ALARM_NAME), - config.get('code'), - config.get('pending_time', DEFAULT_PENDING_TIME), - config.get('trigger_time', DEFAULT_TRIGGER_TIME), + config[CONF_NAME], + config.get(CONF_CODE), + config.get(CONF_PENDING_TIME, DEFAULT_PENDING_TIME), + config.get(CONF_TRIGGER_TIME, DEFAULT_TRIGGER_TIME), + config.get(CONF_DISARM_AFTER_TRIGGER, DEFAULT_DISARM_AFTER_TRIGGER) )]) @@ -40,10 +58,12 @@ class ManualAlarm(alarm.AlarmControlPanel): When armed, will be pending for 'pending_time', after that armed. When triggered, will be pending for 'trigger_time'. After that will be - triggered for 'trigger_time', after that we return to the previous state. + triggered for 'trigger_time', after that we return to the previous state + or disarm if `disarm_after_trigger` is true. """ - def __init__(self, hass, name, code, pending_time, trigger_time): + def __init__(self, hass, name, code, pending_time, + trigger_time, disarm_after_trigger): """Initalize the manual alarm panel.""" self._state = STATE_ALARM_DISARMED self._hass = hass @@ -51,6 +71,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._code = str(code) if code else None self._pending_time = datetime.timedelta(seconds=pending_time) self._trigger_time = datetime.timedelta(seconds=trigger_time) + self._disarm_after_trigger = disarm_after_trigger self._pre_trigger_state = self._state self._state_ts = None @@ -78,7 +99,10 @@ class ManualAlarm(alarm.AlarmControlPanel): return STATE_ALARM_PENDING elif (self._state_ts + self._pending_time + self._trigger_time) < dt_util.utcnow(): - return self._pre_trigger_state + if self._disarm_after_trigger: + return STATE_ALARM_DISARMED + else: + return self._pre_trigger_state return self._state diff --git a/homeassistant/const.py b/homeassistant/const.py index 6dac4acbaf0..c4a48a8d5be 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -26,7 +26,9 @@ CONF_API_KEY = 'api_key' CONF_BEFORE = 'before' CONF_BELOW = 'below' CONF_CONDITION = 'condition' +CONF_CODE = 'code' CONF_CUSTOMIZE = 'customize' +CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_ELEVATION = 'elevation' CONF_ENTITY_ID = 'entity_id' CONF_ENTITY_NAMESPACE = 'entity_namespace' @@ -42,13 +44,15 @@ CONF_NAME = 'name' CONF_OFFSET = 'offset' CONF_OPTIMISTIC = 'optimistic' CONF_PASSWORD = 'password' +CONF_PENDING_TIME = 'pending_time' CONF_PLATFORM = 'platform' CONF_PORT = 'port' CONF_SCAN_INTERVAL = 'scan_interval' CONF_STATE = 'state' CONF_TEMPERATURE_UNIT = 'temperature_unit' -CONF_UNIT_SYSTEM = 'unit_system' CONF_TIME_ZONE = 'time_zone' +CONF_TRIGGER_TIME = 'trigger_time' +CONF_UNIT_SYSTEM = 'unit_system' CONF_USERNAME = 'username' CONF_VALUE_TEMPLATE = 'value_template' CONF_WEEKDAY = 'weekday' diff --git a/tests/components/alarm_control_panel/test_manual.py b/tests/components/alarm_control_panel/test_manual.py index 55bb6b36646..e77180a8bc2 100644 --- a/tests/components/alarm_control_panel/test_manual.py +++ b/tests/components/alarm_control_panel/test_manual.py @@ -32,7 +32,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 0 + 'pending_time': 0, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -53,7 +54,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 1 + 'pending_time': 1, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -83,7 +85,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 1 + 'pending_time': 1, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -104,7 +107,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 0 + 'pending_time': 0, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -125,7 +129,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 1 + 'pending_time': 1, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -155,7 +160,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'code': CODE, - 'pending_time': 1 + 'pending_time': 1, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -175,7 +181,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'alarm_control_panel': { 'platform': 'manual', 'name': 'test', - 'trigger_time': 0 + 'trigger_time': 0, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -196,7 +203,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'pending_time': 2, - 'trigger_time': 3 + 'trigger_time': 3, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -228,13 +236,45 @@ class TestAlarmControlPanelManual(unittest.TestCase): self.assertEqual(STATE_ALARM_DISARMED, self.hass.states.get(entity_id).state) + def test_trigger_with_disarm_after_trigger(self): + """Test disarm after trigger.""" + self.assertTrue(alarm_control_panel.setup(self.hass, { + 'alarm_control_panel': { + 'platform': 'manual', + 'name': 'test', + 'trigger_time': 5, + 'pending_time': 0, + 'disarm_after_trigger': True + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass, entity_id=entity_id) + self.hass.pool.block_till_done() + + self.assertEqual(STATE_ALARM_TRIGGERED, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=5) + with patch(('homeassistant.components.alarm_control_panel.manual.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + def test_disarm_while_pending_trigger(self): """Test disarming while pending state.""" self.assertTrue(alarm_control_panel.setup(self.hass, { 'alarm_control_panel': { 'platform': 'manual', 'name': 'test', - 'trigger_time': 5 + 'trigger_time': 5, + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' @@ -270,7 +310,8 @@ class TestAlarmControlPanelManual(unittest.TestCase): 'platform': 'manual', 'name': 'test', 'pending_time': 5, - 'code': CODE + '2' + 'code': CODE + '2', + 'disarm_after_trigger': False }})) entity_id = 'alarm_control_panel.test' From 8ba85effd4e263fc813839d667b25c02c2b2cf9f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 13 Aug 2016 12:02:13 -0700 Subject: [PATCH 003/193] Version bump to 0.27.0.dev0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 7161f319b30..947d8d32263 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """Constants used by Home Assistant components.""" -__version__ = "0.26.0" +__version__ = "0.27.0.dev0" REQUIRED_PYTHON_VER = (3, 4) PLATFORM_FORMAT = '{}.{}' From 8329472c72029b8a463233717e329db5f933a5f6 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Sat, 13 Aug 2016 23:16:06 +0200 Subject: [PATCH 004/193] Bugfix: removed conf_platform (#2811) * Bugfix: removed conf_platform * Remove unused import * Fix for wrong update --- homeassistant/components/sensor/serial_pm.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/serial_pm.py b/homeassistant/components/sensor/serial_pm.py index f625affce2c..a86fea74cea 100644 --- a/homeassistant/components/sensor/serial_pm.py +++ b/homeassistant/components/sensor/serial_pm.py @@ -7,7 +7,7 @@ https://home-assistant.io/components/sensor.serial_pm/ import logging import voluptuous as vol -from homeassistant.const import CONF_NAME, CONF_PLATFORM +from homeassistant.const import CONF_NAME from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA @@ -21,7 +21,6 @@ CONF_SERIAL_DEVICE = "serial_device" CONF_BRAND = "brand" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_PLATFORM): 'serial_pm', vol.Optional(CONF_NAME, default=""): cv.string, vol.Required(CONF_SERIAL_DEVICE): cv.string, vol.Required(CONF_BRAND): cv.string, From c6f67a52038c73d689f888ae72203dc0f6f595d5 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Sun, 14 Aug 2016 10:02:26 +0200 Subject: [PATCH 005/193] =?UTF-8?q?Implemented=20range=20checking=20for=20?= =?UTF-8?q?temperature=20and=20humidity.=20Out-of-range=E2=80=A6=20(#2805)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implemented range checking for temperature and humidity. Out-of-range values will be ignored * Removed unused import * Use celsius_to_fahrenheit conversion method --- homeassistant/components/sensor/dht.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/sensor/dht.py b/homeassistant/components/sensor/dht.py index ec33b1e4042..170c63a2620 100644 --- a/homeassistant/components/sensor/dht.py +++ b/homeassistant/components/sensor/dht.py @@ -102,12 +102,16 @@ class DHTSensor(Entity): data = self.dht_client.data if self.type == 'temperature': - self._state = round(data['temperature'], 1) - if self.temp_unit == TEMP_FAHRENHEIT: - self._state = round(celsius_to_fahrenheit(data['temperature']), - 1) + temperature = round(data['temperature'], 1) + if (temperature >= -20) and (temperature < 80): + self._state = temperature + if self.temp_unit == TEMP_FAHRENHEIT: + self._state = round(celsius_to_fahrenheit(temperature), + 1) elif self.type == 'humidity': - self._state = round(data['humidity'], 1) + humidity = round(data['humidity'], 1) + if (humidity >= 0) and (humidity <= 100): + self._state = humidity class DHTClient(object): From dc68f61261b171b77e9c4f1a5f8625d42ab1ba88 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 14 Aug 2016 01:10:07 -0700 Subject: [PATCH 006/193] Html5 push notifications notify platform (#2807) * Initial work to add Chrome Push Notification support * Remove push.js from home-assistant since it is now in Polymer * Chrome->HTML5, general cleanup/fixes * Make html5 generic, move manifest.json into frontend so that we can dynamically add the gcm_sender_id * Pylint, flake8, pydocstyle frontend init * HTML5 push fixes * Update polymer * Remove crypto req * Add notify default platform. * Fix HTML5 push * Registration fixes * Linting fix * pep257 fix * Add tests * pep257 fix * Update frontend --- homeassistant/components/frontend/__init__.py | 40 ++++ .../components/frontend/templates/index.html | 2 +- homeassistant/components/frontend/version.py | 4 +- .../components/frontend/www_static/core.js | 8 +- .../components/frontend/www_static/core.js.gz | Bin 31475 -> 31500 bytes .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 122766 -> 123182 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/manifest.json | 30 --- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 1832 -> 2012 bytes homeassistant/components/notify/__init__.py | 13 +- homeassistant/components/notify/html5.py | 173 ++++++++++++++++++ requirements_all.txt | 3 + script/build_frontend | 2 +- tests/components/notify/test_html5.py | 145 +++++++++++++++ 16 files changed, 381 insertions(+), 45 deletions(-) delete mode 100644 homeassistant/components/frontend/www_static/manifest.json create mode 100644 homeassistant/components/notify/html5.py create mode 100644 tests/components/notify/test_html5.py diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index cec18b66511..ab967fb114f 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -14,6 +14,19 @@ URL_PANEL_COMPONENT = '/frontend/panels/{}.html' URL_PANEL_COMPONENT_FP = '/frontend/panels/{}-{}.html' STATIC_PATH = os.path.join(os.path.dirname(__file__), 'www_static') PANELS = {} +MANIFEST_JSON = { + "background_color": "#FFFFFF", + "description": "Open-source home automation platform running on Python 3.", + "dir": "ltr", + "display": "standalone", + "icons": [], + "lang": "en-US", + "name": "Home Assistant", + "orientation": "any", + "short_name": "Assistant", + "start_url": "/", + "theme_color": "#03A9F4" +} # To keep track we don't register a component twice (gives a warning) _REGISTERED_COMPONENTS = set() @@ -94,9 +107,15 @@ def register_panel(hass, component_name, path, md5=None, sidebar_title=None, PANELS[url_path] = data +def add_manifest_json_key(key, val): + """Add a keyval to the manifest.json.""" + MANIFEST_JSON[key] = val + + def setup(hass, config): """Setup serving the frontend.""" hass.wsgi.register_view(BootstrapView) + hass.wsgi.register_view(ManifestJSONView) if hass.wsgi.development: sw_path = "home-assistant-polymer/build/service_worker.js" @@ -126,6 +145,13 @@ def setup(hass, config): hass.bus.listen_once(EVENT_HOMEASSISTANT_START, register_frontend_index) + for size in (192, 384, 512, 1024): + MANIFEST_JSON['icons'].append({ + "src": "/static/icons/favicon-{}x{}.png".format(size, size), + "sizes": "{}x{}".format(size, size), + "type": "image/png" + }) + return True @@ -199,3 +225,17 @@ class IndexView(HomeAssistantView): panel_url=panel_url, panels=PANELS) return self.Response(resp, mimetype='text/html') + + +class ManifestJSONView(HomeAssistantView): + """View to return a manifest.json.""" + + requires_auth = False + url = "/manifest.json" + name = "manifestjson" + + def get(self, request): + """Return the manifest.json.""" + import json + msg = json.dumps(MANIFEST_JSON, sort_keys=True).encode('UTF-8') + return self.Response(msg, mimetype="application/manifest+json") diff --git a/homeassistant/components/frontend/templates/index.html b/homeassistant/components/frontend/templates/index.html index 859b2af53f0..afa9ca68af9 100644 --- a/homeassistant/components/frontend/templates/index.html +++ b/homeassistant/components/frontend/templates/index.html @@ -4,7 +4,7 @@ Home Assistant - + diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index f7c483b3d71..ec30e4804c7 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,8 +1,8 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "457d5acd123e7dc38947c07984b3a5e8", - "frontend.html": "829ee7cb591b8a63d7f22948a7aeb07a", + "core.js": "b4ee3a700ef5549a36b436611e27d3a9", + "frontend.html": "411fcc6c69b3cab0740ac3db4b9947c8", "mdi.html": "b399b5d3798f5b68b0a4fbaae3432d48", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index beb5b8c03e0..4def07355e1 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&&"object"==typeof t&&"default"in t?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 De({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ce.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 Re({authToken:n,host:r})}function u(){return Le.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 Pe.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?Be({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||Be;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.send(JSON.stringify(r)):u.send()})}function A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c199&&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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),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 J4bqgj0RT&HiiH3G delta 30475 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 S?soVB!tg)62HeC>xB&oz{8p6! diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index ce85cdc4f52..cd17014be89 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ },_distributeDirtyRoots:function(){for(var e,t=this.shadyRoot._dirtyRoots,o=0,i=t.length;o0?~setTimeout(e,t):(this._twiddle.textContent=this._twiddleContent++,this._callbacks.push(e),this._currVal++)},cancel:function(e){if(e<0)clearTimeout(~e);else{var t=e-this._lastVal;if(t>=0){if(!this._callbacks[t])throw"invalid async handle: "+e;this._callbacks[t]=null}}},_atEndOfMicrotask:function(){for(var e=this._callbacks.length,t=0;t \ No newline at end of file +this.currentTarget=t,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()},i=window.Element.prototype.animate;window.Element.prototype.animate=function(n,r){var o=i.call(this,n,r);o._cancelHandlers=[],o.oncancel=null;var a=o.cancel;o.cancel=function(){a.call(this);var i=new e(this,null,t()),n=this._cancelHandlers.concat(this.oncancel?[this.oncancel]:[]);setTimeout(function(){n.forEach(function(t){t.call(i.target,i)})},0)};var s=o.addEventListener;o.addEventListener=function(t,e){"function"==typeof e&&"cancel"==t?this._cancelHandlers.push(e):s.call(this,t,e)};var u=o.removeEventListener;return o.removeEventListener=function(t,e){if("cancel"==t){var i=this._cancelHandlers.indexOf(e);i>=0&&this._cancelHandlers.splice(i,1)}else u.call(this,t,e)},o}}}(),function(t){var e=document.documentElement,i=null,n=!1;try{var r=getComputedStyle(e).getPropertyValue("opacity"),o="0"==r?"1":"0";i=e.animate({opacity:[o,o]},{duration:1}),i.currentTime=0,n=getComputedStyle(e).getPropertyValue("opacity")==o}catch(t){}finally{i&&i.cancel()}if(!n){var a=window.Element.prototype.animate;window.Element.prototype.animate=function(e,i){return window.Symbol&&Symbol.iterator&&Array.prototype.from&&e[Symbol.iterator]&&(e=Array.from(e)),Array.isArray(e)||null===e||(e=t.convertToArrayForm(e)),a.call(this,e,i)}}}(c),!function(t,e,i){function n(t){var i=e.timeline;i.currentTime=t,i._discardAnimations(),0==i._animations.length?o=!1:requestAnimationFrame(n)}var r=window.requestAnimationFrame;window.requestAnimationFrame=function(t){return r(function(i){e.timeline._updateAnimationsPromises(),t(i),e.timeline._updateAnimationsPromises()})},e.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},e.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},_updateAnimationsPromises:function(){e.animationsWithPromises=e.animationsWithPromises.filter(function(t){return t._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(t){return"finished"!=t.playState&&"idle"!=t.playState})},_play:function(t){var i=new e.Animation(t,this);return this._animations.push(i),e.restartWebAnimationsNextTick(),i._updatePromises(),i._animation.play(),i._updatePromises(),i},play:function(t){return t&&t.remove(),this._play(t)}};var o=!1;e.restartWebAnimationsNextTick=function(){o||(o=!0,requestAnimationFrame(n))};var a=new e.AnimationTimeline;e.timeline=a;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return a}})}catch(t){}try{window.document.timeline=a}catch(t){}}(c,e,f),function(t,e,i){e.animationsWithPromises=[],e.Animation=function(e,i){if(this.id="",e&&e._id&&(this.id=e._id),this.effect=e,e&&(e._animation=this),!i)throw new Error("Animation with null timeline is not supported");this._timeline=i,this._sequenceNumber=t.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},e.Animation.prototype={_updatePromises:function(){var t=this._oldPlayState,e=this.playState;return this._readyPromise&&e!==t&&("idle"==e?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==t?this._resolveReadyPromise():"pending"==e&&(this._readyPromise=void 0)),this._finishedPromise&&e!==t&&("idle"==e?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==e?this._resolveFinishedPromise():"finished"==t&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var t,i,n,r,o=!!this._animation;o&&(t=this.playbackRate,i=this._paused,n=this.startTime,r=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=e.newUnderlyingAnimationForKeyframeEffect(this.effect),e.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=e.newUnderlyingAnimationForGroup(this.effect),e.bindAnimationForGroup(this)),this.effect&&this.effect._onsample&&e.bindAnimationForCustomEffect(this),o&&(1!=t&&(this.playbackRate=t),null!==n?this.startTime=n:null!==r?this.currentTime=r:null!==this._holdTime&&(this.currentTime=this._holdTime),i&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var t=this.effect._timing.delay;this._childAnimations.forEach(function(i){this._arrangeChildren(i,t),this.effect instanceof window.SequenceEffect&&(t+=e.groupChildDuration(i.effect))}.bind(this))}},_setExternalAnimation:function(t){if(this.effect&&this._isGroup)for(var e=0;e \ 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 5997604af41f092d714acb6e8488377585485860..41c7c071ac75a40a401361571b9fd1358c21cd49 100644 GIT binary patch delta 11904 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 Gl?MQa&PeJ2 delta 11500 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 diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 474366c536e..af4af1e9332 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 474366c536ec3e471da12d5f15b07b79fe9b07e2 +Subproject commit af4af1e9332afef90d25d61589840d239baf7ded diff --git a/homeassistant/components/frontend/www_static/manifest.json b/homeassistant/components/frontend/www_static/manifest.json deleted file mode 100644 index 4cd13ad5470..00000000000 --- a/homeassistant/components/frontend/www_static/manifest.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "Home Assistant", - "short_name": "Assistant", - "start_url": "/", - "display": "standalone", - "theme_color": "#03A9F4", - "background_color": "#FFFFFF", - "icons": [ - { - "src": "/static/icons/favicon-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/static/icons/favicon-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "/static/icons/favicon-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "/static/icons/favicon-1024x1024.png", - "sizes": "1024x1024", - "type": "image/png" - } - ] -} diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index d3a04d4e9b3..40e47f06969 100644 --- a/homeassistant/components/frontend/www_static/service_worker.js +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -1 +1 @@ -"use strict";function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}var precacheConfig=[["/","a463cb982f337e09c3ed47c41b2d9dda"],["/frontend/panels/dev-event-3cc881ae8026c0fba5aa67d334a3ab2b.html","e22ed0d2d10777c87eb9620d81f525b4"],["/frontend/panels/dev-info-34e2df1af32e60fffcafe7e008a92169.html","7e939dc762dc0c0ec769db4ea76a4b09"],["/frontend/panels/dev-service-bb5c587ada694e0fd42ceaaedd6fe6aa.html","782c4860c5e8ab274231ba9dfd528f29"],["/frontend/panels/dev-state-4608326978256644c42b13940c028e0a.html","26758b741ac1b7c8e9cfcb24762d8774"],["/frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html","99114026cf9193263c74cc25f9f6a469"],["/frontend/panels/map-af7d04aff7dd5479c5a0016bc8d4dd7d.html","6031df1b4d23d5b321208449b2d293f8"],["/static/core-457d5acd123e7dc38947c07984b3a5e8.js","69e2a5b421d7ed7a7e70390cd9ced80e"],["/static/frontend-829ee7cb591b8a63d7f22948a7aeb07a.html","2afa980f1c1fdf9e596580112ac8e51a"],["/static/mdi-b399b5d3798f5b68b0a4fbaae3432d48.html","819d479ae2b690589687469045b22c26"],["static/fonts/roboto/Roboto-Bold.ttf","d329cc8b34667f114a95422aaad1b063"],["static/fonts/roboto/Roboto-Light.ttf","7b5fb88f12bec8143f00e21bc3222124"],["static/fonts/roboto/Roboto-Medium.ttf","fe13e4170719c2fc586501e777bde143"],["static/fonts/roboto/Roboto-Regular.ttf","ac3f799d5bbaf5196fab15ab8de8431c"],["static/icons/favicon-192x192.png","419903b8422586a7e28021bbe9011175"],["static/icons/favicon.ico","04235bda7843ec2fceb1cbe2bc696cf4"],["static/images/card_media_player_bg.png","a34281d1c1835d338a642e90930e61aa"],["static/webcomponents-lite.min.js","b0f32ad3c7749c40d486603f31c9d8b1"]],cacheName="sw-precache-v2--"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var a=new URL(e);return"/"===a.pathname.slice(-1)&&(a.pathname+=t),a.toString()},createCacheKey=function(e,t,a,n){var c=new URL(e);return n&&c.toString().match(n)||(c.search+=(c.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(a)),c.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var a=new URL(t).pathname;return e.some(function(e){return a.match(e)})},stripIgnoredUrlParameters=function(e,t){var a=new URL(e);return a.search=a.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(e){return t.every(function(t){return!t.test(e[0])})}).map(function(e){return e.join("=")}).join("&"),a.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],a=e[1],n=new URL(t,self.location),c=createCacheKey(n,hashParamName,a,!1);return[n.toString(),c]}));self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(e){return setOfCachedUrls(e).then(function(t){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(a){if(!t.has(a))return e.add(new Request(a,{credentials:"same-origin"}))}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var t=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(e){return e.keys().then(function(a){return Promise.all(a.map(function(a){if(!t.has(a.url))return e.delete(a)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(e){if("GET"===e.request.method){var t,a=stripIgnoredUrlParameters(e.request.url,ignoreUrlParametersMatching);t=urlsToCacheKeys.has(a);var n="index.html";!t&&n&&(a=addDirectoryIndex(a,n),t=urlsToCacheKeys.has(a));var c="/";!t&&c&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js)).)*$"],e.request.url)&&(a=new URL(c,self.location).toString(),t=urlsToCacheKeys.has(a)),t&&e.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(a))}).catch(function(t){return console.warn('Couldn\'t serve response for "%s" from cache: %O',e.request.url,t),fetch(e.request)}))}}); \ No newline at end of file +"use strict";function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}var precacheConfig=[["/","9a5d0507bd1f13e3eca6b35abd4cbebb"],["/frontend/panels/dev-event-3cc881ae8026c0fba5aa67d334a3ab2b.html","e22ed0d2d10777c87eb9620d81f525b4"],["/frontend/panels/dev-info-34e2df1af32e60fffcafe7e008a92169.html","7e939dc762dc0c0ec769db4ea76a4b09"],["/frontend/panels/dev-service-bb5c587ada694e0fd42ceaaedd6fe6aa.html","782c4860c5e8ab274231ba9dfd528f29"],["/frontend/panels/dev-state-4608326978256644c42b13940c028e0a.html","26758b741ac1b7c8e9cfcb24762d8774"],["/frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html","99114026cf9193263c74cc25f9f6a469"],["/frontend/panels/map-af7d04aff7dd5479c5a0016bc8d4dd7d.html","6031df1b4d23d5b321208449b2d293f8"],["/static/core-b4ee3a700ef5549a36b436611e27d3a9.js","e2fb4f1dc0d1e8192a327b51768b3802"],["/static/frontend-411fcc6c69b3cab0740ac3db4b9947c8.html","5967b9cdaeb14753552c2461805eb397"],["/static/mdi-b399b5d3798f5b68b0a4fbaae3432d48.html","819d479ae2b690589687469045b22c26"],["static/fonts/roboto/Roboto-Bold.ttf","d329cc8b34667f114a95422aaad1b063"],["static/fonts/roboto/Roboto-Light.ttf","7b5fb88f12bec8143f00e21bc3222124"],["static/fonts/roboto/Roboto-Medium.ttf","fe13e4170719c2fc586501e777bde143"],["static/fonts/roboto/Roboto-Regular.ttf","ac3f799d5bbaf5196fab15ab8de8431c"],["static/icons/favicon-192x192.png","419903b8422586a7e28021bbe9011175"],["static/icons/favicon.ico","04235bda7843ec2fceb1cbe2bc696cf4"],["static/images/card_media_player_bg.png","a34281d1c1835d338a642e90930e61aa"],["static/webcomponents-lite.min.js","b0f32ad3c7749c40d486603f31c9d8b1"]],cacheName="sw-precache-v2--"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},createCacheKey=function(e,t,n,a){var c=new URL(e);return a&&c.toString().match(a)||(c.search+=(c.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),c.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,t){var n=new URL(e);return n.search=n.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(e){return t.every(function(t){return!t.test(e[0])})}).map(function(e){return e.join("=")}).join("&"),n.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],a=new URL(t,self.location),c=createCacheKey(a,hashParamName,n,!1);return[a.toString(),c]}));self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(e){return setOfCachedUrls(e).then(function(t){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(n){if(!t.has(n))return e.add(new Request(n,{credentials:"same-origin"}))}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var t=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(e){return e.keys().then(function(n){return Promise.all(n.map(function(n){if(!t.has(n.url))return e.delete(n)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(e){if("GET"===e.request.method){var t,n=stripIgnoredUrlParameters(e.request.url,ignoreUrlParametersMatching);t=urlsToCacheKeys.has(n);var a="index.html";!t&&a&&(n=addDirectoryIndex(n,a),t=urlsToCacheKeys.has(n));var c="/";!t&&c&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(n=new URL(c,self.location).toString(),t=urlsToCacheKeys.has(n)),t&&e.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n))}).catch(function(t){return console.warn('Couldn\'t serve response for "%s" from cache: %O',e.request.url,t),fetch(e.request)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t)))}),self.addEventListener("notificationclick",function(e){var t;e.notification.data&&e.notification.data.url&&(e.notification.close(),t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var n,a;for(n=0;n<<(saSpt-a~W+K*c3esQmqS%Ce}RBZ^+*9N+E<42Huftxmrl5PP$+-*2muvDw# zFV;=h6Qyol1Mhea{iFVQ~6T%3lDVGAHW(ANtKP=1BLg#`i zLp1^i(m11;=#N*LTIKhazenRsgR0iTJS8R6d1Bh$>ei8u*+%TDCXQ!D5zwL zvs|Y%&kD_vng@1w2bc&-oiUloq~=Cxk_(~?N4jV!1wy@xI+aj(~XJHGK zOB$G$sA8&Dl$Vd5B(14e@FEDJxSV^eQ53azszHk#H0@i}nMLVQU(SDDcgxH3i&$Cv zj}rZKb#wFDTliykFIRCFeeK1`&w9Q3@cs?z)pVm^C{MH5%qJ_=Ej(IJ+6wz~IHA#a z9Ns@Zn{`p_ldk?1b=S|s=v!wF>? z(J&RA^!2$e{m#|q9z%P;pM`1{0|uKix!kLhAjY|?{jJ`Ss~ymIi{1{$t49I!&~>vu zz}Vx3Vp-g0E*^@ks?AVf$dB0}g+p~16SDXj-J$9HjxUIXFoDXu2tE6@LgGj!wK31>)VHSjpFo-`FOH@u=FlNqjyccEL%v>efVS3 zsG9_3co{xGGr3aL8gL?hkU>9G0j3#Y=quEGC)xHQ? zjDJ!$<-GI(0yF$P8k+acgRr$<%GF0iWJ892Lwo{Gh1;(%O^0}HGQAtWPabgkf8c)N zyTKnt+dlF24hn1MD`3IAIjQKY#iy7+PDi$zOtP zXHnZNh*&8nJ5zYS2aoWS5=GN)_Am<@8VwCp&9E#`lr}Tj^jS9^t6pGck7O(CwIe=d zY-7#LP__mmW;_l&&J6ROActo}Nf?hGb^Y*D@Ov1(d=_qm{#LEZ+rA}Kx7$yX%j>%N z0u4(2?Na&D^|n5@*e{|a`s-hCMmT_EP|3R%V;;1a{g!d^L@^$tx7ng}*^gzn_}_WD zQJIJK=P>9X^2-eGkMxUv=Blf{Mj9VJe^sw5>;L_{8}(SgXcH5DY`eM{1wXXGsP87D zA*2_hAAWg$hy`j_JTUN{H3MBw^L4du7e~q(i`J^H=Lh!k;daOXg1BGJM@FVaef@LY zm9E_2AEIEDUDb=~Q&r>lwqUiHFULdLU$%|!$ip584E(_xQ`IdDBsj5ULxR0lwXOOg zvp-^g`P$v|Ot6?7T6 u+N@hF&5_!*CzTA(!f1*+c472X{5ZJYEqnYX9I}nS)Bgh1c&Hko5dZ)>6XA^j literal 1832 zcmV+@2iN!?iwFo6QLk4519N3^c4=c}Uw3bEYh`jSYI6XkS8Z?G$PxZ43ej`OhNAb4 z%lb%CarnO0FmnhlIF%X6BifXBeIL zIO~V5azk_y&KoyWZ8Pg}_&K};w?hBEtNR#}&m9iuT{FY%6JGUkk_{_t;@t~-2iCB8 z{K0uwe@(s~ezn2N*)KTIFLdkzy4j{fH#+gMZ9=tNeEb+4M`;AAkj@${f|MmP<0N`j zI>oK<#(RiPQ#u&Bwi&ST#~Wy{?vFiQ%<%%7VJ@B1ngePk3de$l9H1z@lnNwRVYAh+ zuE`Dxfu4EcIV;Q3=@P9e1oN7QT;x_Awo^5solAwn2M$3BELaG^K|u1CX)uBpW@n~E zBaL@uA-rRbA>A2o6+&5nvdkPd(_?p0Ihi$W=*zQH+Do(=GvBugX5Nn zL*s(8LX9Envit^d1FkpqXo>+d#;aVLLKf&HlNuzNzywo;hH_`h7|zw0$6&Z2-=r&* zb0QBW5PQXekf=iE5K7M!1iJWKmB!`37%!~TUU^^oorQu)PHD8t3+Zz!1s6;!WvJMM zkwI@Qj09Eg*tH$el$SmS=edwrdMCA^>SU$S%1R*Wv)}s>*PsBZBEfx$zJwA>CJl4m zIP{v~9_}uHxfTYobT&8KYAB>HgAhg$BY>8bw<&-CMzg>j4?Y;oO_6KHxd2K>&S4LI z?W?(!#@O6Tax>(%(3XLs)&P`B3a|7ISaV8CX#j;S3>)*KOX8WS+zR1DF#+$qCa3%3 zuC?vZ9>1F|^S`&X&xRool$XL#D_W_Fq70NrFu4)}06e#>kl%xPT`gC`HCAc!V6_fh zSag~z85l#st&>7f#?<$)-k`6}*VkYHxkSZFR&wJ+px!ES#*v1A^+?#?1AB+d^BTHq zG;lJMRLr@x5OQvc0G8)qwMVTacX!b$*EaoefQ#{F&W-qk{<2N8Bpk(!VbW@%h#aDN z5j4QKwP+}>yvz^cWb_}svV>!Bp8IEICmJ4<HE>34 zd4=7XU0!uMm4sG4mXSVr>^ zJoRm%ZgMCMn!q? z;Fqj-?FOGmQIb~6hI*7l?JabKIAGVmfx)e+hV!Ng7SO3oU?&dmI zJjwbEm1s;%C5Km;>obdJ+-E{nljX+_4jHW+-PP@*VfW|>O)l(d*ZIg!lW8kDXzTa3 zYIdf!_vG5W`dLB0nmE|D$=RJgiBj6T`d`~!arF}$Z^+vIdiB78k-A|qI+y}o_-WeQ zW-gtYtZv=ZU{oKA{SuCweV?d`pYR>~ADcVQr|$G?lAKI<)OSCPJKF29s2bulsu~(1 zH7UlS0_t<5jrd*$Vd?@(Gtn@1&`mli#(1Rh9scKhtN=(q6Lp@VuAuIpM?LvJZ@X$) zH4zar{d=%9--(B4>pxYS55&l}7{(XU19SqtenDy4=X0Cs-THknz?1)j_XFPz@F?5x zEh@*)h&yz8tf}wm%%363)zzp$bcJgD9jXG-wAts0yomns)34Dq+PZE2G8#Lp)?brI zopNw8#kcQJ2;Wko1XF?yVBeWK6n&~~%vhd!E(^J6x-^nCWi&rkQcAhk-T Wn!Bx&sX)IbC;tV!yL(}!4*&qP>7qdZ diff --git a/homeassistant/components/notify/__init__.py b/homeassistant/components/notify/__init__.py index 4b73c46b198..782a4510ffb 100644 --- a/homeassistant/components/notify/__init__.py +++ b/homeassistant/components/notify/__init__.py @@ -13,9 +13,9 @@ import voluptuous as vol import homeassistant.bootstrap as bootstrap from homeassistant.config import load_yaml_config_file from homeassistant.helpers import config_per_platform, template -from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa import homeassistant.helpers.config_validation as cv -from homeassistant.const import CONF_NAME +from homeassistant.const import CONF_NAME, CONF_PLATFORM +from homeassistant.util import slugify DOMAIN = "notify" @@ -34,6 +34,11 @@ ATTR_DATA = 'data' SERVICE_NOTIFY = "notify" +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): cv.string, + vol.Optional(CONF_NAME): cv.string, +}, extra=vol.ALLOW_EXTRA) + NOTIFY_SERVICE_SCHEMA = vol.Schema({ vol.Required(ATTR_MESSAGE): cv.template, vol.Optional(ATTR_TITLE, default=ATTR_TITLE_DEFAULT): cv.string, @@ -95,8 +100,8 @@ def setup(hass, config): data=data) service_call_handler = partial(notify_message, notify_service) - service_notify = p_config.get(CONF_NAME, SERVICE_NOTIFY) - hass.services.register(DOMAIN, service_notify, service_call_handler, + service_name = slugify(p_config.get(CONF_NAME) or SERVICE_NOTIFY) + hass.services.register(DOMAIN, service_name, service_call_handler, descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA) success = True diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py new file mode 100644 index 00000000000..70ab9580a04 --- /dev/null +++ b/homeassistant/components/notify/html5.py @@ -0,0 +1,173 @@ +""" +HTML5 Push Messaging notification service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.html5/ +""" +import os +import logging +import json + +import voluptuous as vol +from voluptuous.humanize import humanize_error + +from homeassistant.const import ( + HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR) +from homeassistant.util import ensure_unique_string +from homeassistant.components.notify import ( + ATTR_TARGET, ATTR_DATA, BaseNotificationService, + PLATFORM_SCHEMA) +from homeassistant.components.http import HomeAssistantView +from homeassistant.components.frontend import add_manifest_json_key +from homeassistant.helpers import config_validation as cv + +REQUIREMENTS = ['https://github.com/web-push-libs/pywebpush/archive/' + 'e743dc92558fc62178d255c0018920d74fa778ed.zip#' + 'pywebpush==0.5.0'] + +DEPENDENCIES = ["frontend"] + +_LOGGER = logging.getLogger(__name__) + +REGISTRATIONS_FILE = "html5_push_registrations.conf" + +ATTR_GCM_SENDER_ID = 'gcm_sender_id' +ATTR_GCM_API_KEY = 'gcm_api_key' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(ATTR_GCM_SENDER_ID): cv.string, + vol.Optional(ATTR_GCM_API_KEY): cv.string, +}) + +ATTR_SUBSCRIPTION = 'subscription' +ATTR_BROWSER = 'browser' + +REGISTER_SCHEMA = vol.Schema({ + vol.Required(ATTR_SUBSCRIPTION): cv.match_all, + vol.Required(ATTR_BROWSER): vol.In(['chrome', 'firefox']) +}) + + +def get_service(hass, config): + """Get the HTML5 push notification service.""" + json_path = hass.config.path(REGISTRATIONS_FILE) + + registrations = _load_config(json_path) + + if registrations is None: + return None + + hass.wsgi.register_view( + HTML5PushRegistrationView(hass, registrations, json_path)) + + gcm_api_key = config.get('gcm_api_key') + gcm_sender_id = config.get('gcm_sender_id') + + if gcm_sender_id is not None: + add_manifest_json_key('gcm_sender_id', config.get('gcm_sender_id')) + + return HTML5NotificationService(gcm_api_key, registrations) + + +def _load_config(filename): + """Load configuration.""" + if not os.path.isfile(filename): + return {} + + try: + with open(filename, "r") as fdesc: + inp = fdesc.read() + + # In case empty file + if not inp: + return {} + + return json.loads(inp) + except (IOError, ValueError) as error: + _LOGGER.error("Reading config file %s failed: %s", filename, error) + return None + + +def _save_config(filename, config): + """Save configuration.""" + try: + with open(filename, "w") as fdesc: + fdesc.write(json.dumps(config, indent=4, sort_keys=True)) + except (IOError, TypeError) as error: + _LOGGER.error("Saving config file failed: %s", error) + return False + return True + + +class HTML5PushRegistrationView(HomeAssistantView): + """Accepts push registrations from a browser.""" + + url = "/api/notify.html5" + name = "api:notify.html5" + + def __init__(self, hass, registrations, json_path): + """Init HTML5PushRegistrationView.""" + super().__init__(hass) + self.registrations = registrations + self.json_path = json_path + + def post(self, request): + """Accept the POST request for push registrations from a browser.""" + try: + data = REGISTER_SCHEMA(request.json) + except vol.Invalid as ex: + return self.json_message(humanize_error(request.json, ex), + HTTP_BAD_REQUEST) + + name = ensure_unique_string('unnamed device', + self.registrations.keys()) + + self.registrations[name] = data + + if not _save_config(self.json_path, self.registrations): + return self.json_message('Error saving registration.', + HTTP_INTERNAL_SERVER_ERROR) + + return self.json_message("Push notification subscriber registered.") + + +# pylint: disable=too-few-public-methods +class HTML5NotificationService(BaseNotificationService): + """Implement the notification service for HTML5.""" + + # pylint: disable=too-many-arguments + def __init__(self, gcm_key, registrations): + """Initialize the service.""" + self._gcm_key = gcm_key + self.registrations = registrations + + def send_message(self, message="", **kwargs): + """Send a message to a user.""" + from pywebpush import WebPusher + + payload = { + 'title': message, + 'icon': '/static/icons/favicon-192x192.png', + } + + data = kwargs.get(ATTR_DATA) + + if data: + payload.update(data) + + targets = kwargs.get(ATTR_TARGET) + + if not targets: + targets = self.registrations.keys() + elif not isinstance(targets, list): + targets = [targets] + + for target in targets: + info = self.registrations.get(target) + if info is None: + _LOGGER.error("%s is not a valid HTML5 push notification" + " target!", target) + continue + + WebPusher(info[ATTR_SUBSCRIPTION]).send( + json.dumps(payload), gcm_key=self._gcm_key, ttl='0') diff --git a/requirements_all.txt b/requirements_all.txt index e2be50c8f4d..4c1078c1968 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -181,6 +181,9 @@ https://github.com/theolind/pymysensors/archive/cc5d0b325e13c2b623fa934f69eea7cd # homeassistant.components.alarm_control_panel.simplisafe https://github.com/w1ll1am23/simplisafe-python/archive/586fede0e85fd69e56e516aaa8e97eb644ca8866.zip#simplisafe-python==0.0.1 +# homeassistant.components.notify.html5 +https://github.com/web-push-libs/pywebpush/archive/e743dc92558fc62178d255c0018920d74fa778ed.zip#pywebpush==0.5.0 + # homeassistant.components.media_player.lg_netcast https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0 diff --git a/script/build_frontend b/script/build_frontend index da484a943b0..a00f89f1eea 100755 --- a/script/build_frontend +++ b/script/build_frontend @@ -10,7 +10,7 @@ npm run frontend_prod cp bower_components/webcomponentsjs/webcomponents-lite.min.js .. cp -r build/* .. -node script/sw-precache.js +BUILD_DEV=0 node script/gen-service-worker.js cp build/service_worker.js .. cd .. diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py new file mode 100644 index 00000000000..b562775d32e --- /dev/null +++ b/tests/components/notify/test_html5.py @@ -0,0 +1,145 @@ +"""Test HTML5 notify platform.""" +import json +import tempfile +from unittest.mock import patch, MagicMock + +from werkzeug.test import EnvironBuilder + +from homeassistant.components.http import request_class +from homeassistant.components.notify import html5 + + +class TestHtml5Notify(object): + """Tests for HTML5 notify platform.""" + + def test_get_service_with_no_json(self): + """Test empty json file.""" + hass = MagicMock() + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + service = html5.get_service(hass, {}) + + assert service is not None + + def test_get_service_with_bad_json(self): + """Test .""" + hass = MagicMock() + + with tempfile.NamedTemporaryFile() as fp: + fp.write('I am not JSON'.encode('utf-8')) + fp.flush() + hass.config.path.return_value = fp.name + service = html5.get_service(hass, {}) + + assert service is None + + @patch('pywebpush.WebPusher') + def test_sending_message(self, mock_wp): + """Test sending message.""" + hass = MagicMock() + + data = { + 'device': { + 'browser': 'chrome', + 'subscription': 'hello world', + } + } + + with tempfile.NamedTemporaryFile() as fp: + fp.write(json.dumps(data).encode('utf-8')) + fp.flush() + hass.config.path.return_value = fp.name + service = html5.get_service(hass, {'gcm_sender_id': '100'}) + + assert service is not None + + service.send_message('Hello', target=['device', 'non_existing'], + data={'icon': 'beer.png'}) + + assert len(mock_wp.mock_calls) == 2 + + # WebPusher constructor + assert mock_wp.mock_calls[0][1][0] == 'hello world' + + # Call to send + payload = json.loads(mock_wp.mock_calls[1][1][0]) + + assert payload['title'] == 'Hello' + assert payload['icon'] == 'beer.png' + + def test_registering_new_device_view(self): + """Test that the HTML view works.""" + hass = MagicMock() + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + fp.close() + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 2 + + view = hass.mock_calls[1][1][0] + assert view.json_path == fp.name + assert view.registrations == {} + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'browser': 'chrome', + 'subscription': 'sub info', + })) + Request = request_class() + resp = view.post(Request(builder.get_environ())) + + expected = { + 'unnamed device': { + 'browser': 'chrome', + 'subscription': 'sub info', + }, + } + + assert resp.status_code == 200, resp.response + assert view.registrations == expected + with open(fp.name) as fpp: + assert json.load(fpp) == expected + + def test_registering_new_device_validation(self): + """Test various errors when registering a new device.""" + hass = MagicMock() + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 2 + + view = hass.mock_calls[1][1][0] + + Request = request_class() + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'browser': 'invalid browser', + 'subscription': 'sub info', + })) + resp = view.post(Request(builder.get_environ())) + assert resp.status_code == 400, resp.response + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'browser': 'chrome', + })) + resp = view.post(Request(builder.get_environ())) + assert resp.status_code == 400, resp.response + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'browser': 'chrome', + 'subscription': 'sub info', + })) + with patch('homeassistant.components.notify.html5._save_config', + return_value=False): + resp = view.post(Request(builder.get_environ())) + assert resp.status_code == 500, resp.response From bb14239d91d6734fff5d9fd055c4bdd30d8cee09 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Sun, 14 Aug 2016 10:19:54 +0200 Subject: [PATCH 007/193] Fix unknown unit of measurement for hvac and thermostat component (#2816) * Fix unknown unit of measurement for hvac and thermostat component * Simplify --- homeassistant/components/hvac/zwave.py | 5 +++-- homeassistant/components/thermostat/zwave.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/hvac/zwave.py b/homeassistant/components/hvac/zwave.py index 2747cc8eb32..f8cb3fa5c9e 100755 --- a/homeassistant/components/hvac/zwave.py +++ b/homeassistant/components/hvac/zwave.py @@ -120,8 +120,9 @@ class ZWaveHvac(ZWaveDeviceEntity, HvacDevice): # Current Temp for value in self._node.get_values( class_id=COMMAND_CLASS_SENSOR_MULTILEVEL).values(): - self._current_temperature = int(value.data) - self._unit = value.units + 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(): diff --git a/homeassistant/components/thermostat/zwave.py b/homeassistant/components/thermostat/zwave.py index 80766d47100..bd5e5d04b58 100644 --- a/homeassistant/components/thermostat/zwave.py +++ b/homeassistant/components/thermostat/zwave.py @@ -91,8 +91,9 @@ class ZWaveThermostat(zwave.ZWaveDeviceEntity, ThermostatDevice): # current Temp for _, value in self._node.get_values_for_command_class( COMMAND_CLASS_SENSOR_MULTILEVEL).items(): - self._current_temperature = int(value.data) - self._unit = value.units + if value.label == 'Temperature': + self._current_temperature = int(value.data) + self._unit = value.units # operation state for _, value in self._node.get_values( From 8210d65850c6ac54f1cbc70077500172fd21b656 Mon Sep 17 00:00:00 2001 From: Heiko Rothe Date: Sun, 14 Aug 2016 10:20:28 +0200 Subject: [PATCH 008/193] Check for existence of system mode on Honeywell thermostats (#2815) * Check for existence of system mode on Honeywell thermostats * Return None instead of undefined * Use getattr instead of if/else --- homeassistant/components/thermostat/honeywell.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/thermostat/honeywell.py b/homeassistant/components/thermostat/honeywell.py index b31dfea0b4b..6d9a4b790eb 100644 --- a/homeassistant/components/thermostat/honeywell.py +++ b/homeassistant/components/thermostat/honeywell.py @@ -139,7 +139,7 @@ class RoundThermostat(ThermostatDevice): @property def operation(self: ThermostatDevice) -> str: """Get the current operation of the system.""" - return self.device.system_mode + return getattr(self.device, 'system_mode', None) @property def is_away_mode_on(self): @@ -148,7 +148,8 @@ class RoundThermostat(ThermostatDevice): def set_hvac_mode(self: ThermostatDevice, hvac_mode: str) -> None: """Set the HVAC mode for the thermostat.""" - self.device.system_mode = hvac_mode + if hasattr(self.device, 'system_mode'): + self.device.system_mode = hvac_mode def turn_away_mode_on(self): """Turn away on. @@ -231,7 +232,7 @@ class HoneywellUSThermostat(ThermostatDevice): @property def operation(self: ThermostatDevice) -> str: """Return current operation ie. heat, cool, idle.""" - return self._device.system_mode + return getattr(self._device, 'system_mode', None) def set_temperature(self, temperature): """Set target temperature.""" @@ -261,4 +262,5 @@ class HoneywellUSThermostat(ThermostatDevice): def set_hvac_mode(self: ThermostatDevice, hvac_mode: str) -> None: """Set the system mode (Cool, Heat, etc).""" - self._device.system_mode = hvac_mode + if hasattr(self._device, 'system_mode'): + self._device.system_mode = hvac_mode From 6fd0fe05f999a154bc8c7fd96be4c9aaffb801db Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Sun, 14 Aug 2016 19:42:43 +0100 Subject: [PATCH 009/193] Bump to pywemo 0.4.5 - fixes bug with requests 2.11.0 (#2818) --- homeassistant/components/wemo.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/wemo.py b/homeassistant/components/wemo.py index 1a32d4c361e..00a7017fa0f 100644 --- a/homeassistant/components/wemo.py +++ b/homeassistant/components/wemo.py @@ -10,7 +10,7 @@ from homeassistant.components.discovery import SERVICE_WEMO from homeassistant.helpers import discovery from homeassistant.const import EVENT_HOMEASSISTANT_STOP -REQUIREMENTS = ['pywemo==0.4.3'] +REQUIREMENTS = ['pywemo==0.4.5'] DOMAIN = 'wemo' diff --git a/requirements_all.txt b/requirements_all.txt index 4c1078c1968..d4612f5c024 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -377,7 +377,7 @@ pyuserinput==0.1.9 pyvera==0.2.15 # homeassistant.components.wemo -pywemo==0.4.3 +pywemo==0.4.5 # homeassistant.components.thermostat.radiotherm radiotherm==1.2 From c0b1ff0eaf8d4ffcee8ce126e16622dee8e28ae7 Mon Sep 17 00:00:00 2001 From: pavoni Date: Mon, 15 Aug 2016 13:08:30 +0100 Subject: [PATCH 010/193] Handle accuracy zero correctly in enter/leave events. --- .../components/device_tracker/owntracks.py | 22 +++++++--- .../device_tracker/test_owntracks.py | 43 +++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index 00ba8c68556..869728f67f9 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -29,6 +29,9 @@ LOCK = threading.Lock() CONF_MAX_GPS_ACCURACY = 'max_gps_accuracy' +VALIDATE_LOCATION = 'location' +VALIDATE_TRANSITION = 'transition' + def setup_scanner(hass, config, see): """Setup an OwnTracks tracker.""" @@ -47,6 +50,8 @@ def setup_scanner(hass, config, see): 'because of missing or malformatted data: %s', data_type, data) return None + if data_type == VALIDATE_TRANSITION: + return data if max_gps_accuracy is not None and \ convert(data.get('acc'), float, 0.0) > max_gps_accuracy: _LOGGER.debug('Skipping %s update because expected GPS ' @@ -65,7 +70,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, 'location') + data = validate_payload(payload, VALIDATE_LOCATION) if not data: return @@ -86,7 +91,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, 'transition') + data = validate_payload(payload, VALIDATE_TRANSITION) if not data: return @@ -143,10 +148,17 @@ def setup_scanner(hass, config, see): else: _LOGGER.info("Exit to GPS") # Check for GPS accuracy - if not ('acc' in data and - max_gps_accuracy is not None and - data['acc'] > max_gps_accuracy): + valid_gps = True + if 'acc' in data: + if data['acc'] == 0.0: + valid_gps = False + _LOGGER.info("Zero GPS reported") + if (max_gps_accuracy is not None and + data['acc'] > max_gps_accuracy): + valid_gps = False + _LOGGER.info("Inaccurate GPS reported") + if valid_gps: see(**kwargs) see_beacons(dev_id, kwargs) else: diff --git a/tests/components/device_tracker/test_owntracks.py b/tests/components/device_tracker/test_owntracks.py index 16fb1c4a4ce..a539afe02f3 100644 --- a/tests/components/device_tracker/test_owntracks.py +++ b/tests/components/device_tracker/test_owntracks.py @@ -108,6 +108,31 @@ REGION_LEAVE_INACCURATE_MESSAGE = { '_type': 'transition'} +REGION_ENTER_ZERO_MESSAGE = { + 'lon': 1.0, + 'event': 'enter', + 'tid': 'user', + 'desc': 'inner', + 'wtst': 1, + 't': 'b', + 'acc': 0, + 'tst': 2, + 'lat': 2.0, + '_type': 'transition'} + +REGION_LEAVE_ZERO_MESSAGE = { + 'lon': 10.0, + 'event': 'leave', + 'tid': 'user', + 'desc': 'inner', + 'wtst': 1, + 't': 'b', + 'acc': 0, + 'tst': 2, + 'lat': 20.0, + '_type': 'transition'} + + class TestDeviceTrackerOwnTracks(unittest.TestCase): """Test the OwnTrack sensor.""" @@ -293,6 +318,24 @@ class TestDeviceTrackerOwnTracks(unittest.TestCase): # But does exit region correctly self.assertFalse(owntracks.REGIONS_ENTERED[USER]) + def test_event_entry_exit_zero_accuracy(self): + self.send_message(EVENT_TOPIC, REGION_ENTER_ZERO_MESSAGE) + + # Enter uses the zone's gps co-ords + self.assert_location_latitude(2.1) + self.assert_location_accuracy(10.0) + self.assert_location_state('inner') + + self.send_message(EVENT_TOPIC, REGION_LEAVE_ZERO_MESSAGE) + + # Exit doesn't use zero gps + self.assert_location_latitude(2.1) + self.assert_location_accuracy(10.0) + self.assert_location_state('inner') + + # But does exit region correctly + self.assertFalse(owntracks.REGIONS_ENTERED[USER]) + def test_event_exit_outside_zone_sets_away(self): """Test the event for exit zone.""" self.send_message(EVENT_TOPIC, REGION_ENTER_MESSAGE) From a7703f27d8883dcf16b94211b4df96e558ae3d32 Mon Sep 17 00:00:00 2001 From: pavoni Date: Mon, 15 Aug 2016 13:14:07 +0100 Subject: [PATCH 011/193] Add missed docstring. --- tests/components/device_tracker/test_owntracks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/components/device_tracker/test_owntracks.py b/tests/components/device_tracker/test_owntracks.py index a539afe02f3..393b61a3134 100644 --- a/tests/components/device_tracker/test_owntracks.py +++ b/tests/components/device_tracker/test_owntracks.py @@ -319,6 +319,7 @@ class TestDeviceTrackerOwnTracks(unittest.TestCase): self.assertFalse(owntracks.REGIONS_ENTERED[USER]) def test_event_entry_exit_zero_accuracy(self): + """Test entry/exit events with accuracy zero.""" self.send_message(EVENT_TOPIC, REGION_ENTER_ZERO_MESSAGE) # Enter uses the zone's gps co-ords From 9afb1d8c0dbacf3f36e3ea6d6513bcd7e13be242 Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Tue, 16 Aug 2016 07:12:43 +0200 Subject: [PATCH 012/193] Fix unit log message (#2823) * Fix log message for deprecated temp key * Use string formatting and pass constant variables as arguments in log message to show correct name of config keys. * Fix import order --- homeassistant/config.py | 5 +++-- homeassistant/util/yaml.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/config.py b/homeassistant/config.py index 65ed44bef83..d67bbea0bc6 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -267,8 +267,9 @@ def process_ha_core_config(hass, config): else: hac.units = IMPERIAL_SYSTEM _LOGGER.warning("Found deprecated temperature unit in core config, " - "expected unit system. Replace 'temperature: %s' with " - "'unit_system: %s'", unit, hac.units.name) + "expected unit system. Replace '%s: %s' with " + "'%s: %s'", CONF_TEMPERATURE_UNIT, unit, + CONF_UNIT_SYSTEM, hac.units.name) # Shortcut if no auto-detection necessary if None not in (hac.latitude, hac.longitude, hac.units, diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 8b2521e3e9b..c88daaab69a 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -1,10 +1,10 @@ """YAML utility functions.""" +import glob import logging import os from collections import OrderedDict from typing import Union, List, Dict -import glob import yaml try: import keyring From 27e27ee1569faf79f66815e37eb1becead075c89 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Tue, 16 Aug 2016 07:13:49 +0200 Subject: [PATCH 013/193] Exit when command_classes are missing thermostat Zwave (#2824) --- homeassistant/components/thermostat/zwave.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/homeassistant/components/thermostat/zwave.py b/homeassistant/components/thermostat/zwave.py index bd5e5d04b58..d44e6b5f70a 100644 --- a/homeassistant/components/thermostat/zwave.py +++ b/homeassistant/components/thermostat/zwave.py @@ -51,6 +51,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_IGNORE: _LOGGER.debug("Remotec ZXT-120 Zwave Thermostat, ignoring") return + if not (value.node.get_values_for_command_class( + COMMAND_CLASS_SENSOR_MULTILEVEL) and + value.node.get_values_for_command_class( + COMMAND_CLASS_THERMOSTAT_SETPOINT)): + return add_devices([ZWaveThermostat(value)]) _LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s", From d281a7260dcdd4330386b5f4e9e9058e5b93414e Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Tue, 16 Aug 2016 01:48:42 -0400 Subject: [PATCH 014/193] check for runtime error during db query (#2834) --- homeassistant/components/sensor/fastdotcom.py | 2 ++ homeassistant/components/sensor/speedtest.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/homeassistant/components/sensor/fastdotcom.py b/homeassistant/components/sensor/fastdotcom.py index fbdf6220c91..db68d505b14 100644 --- a/homeassistant/components/sensor/fastdotcom.py +++ b/homeassistant/components/sensor/fastdotcom.py @@ -78,6 +78,8 @@ class SpeedtestSensor(Entity): ).order_by(states.state_id.desc()).limit(1)) except TypeError: return + except RuntimeError: + return if not last_state: return self._state = last_state[0].state diff --git a/homeassistant/components/sensor/speedtest.py b/homeassistant/components/sensor/speedtest.py index 445bf8a8d4b..1ce653f7ae6 100644 --- a/homeassistant/components/sensor/speedtest.py +++ b/homeassistant/components/sensor/speedtest.py @@ -97,6 +97,8 @@ class SpeedtestSensor(Entity): ).order_by(states.state_id.desc()).limit(1)) except TypeError: return + except RuntimeError: + return if not last_state: return self._state = last_state[0].state From 72ad1d8d7c49172fa80676174a9c22fea89845a5 Mon Sep 17 00:00:00 2001 From: Assaf Inbal Date: Tue, 16 Aug 2016 09:07:07 +0300 Subject: [PATCH 015/193] Added support for exposing light features (#2828) --- homeassistant/components/light/__init__.py | 20 ++++++++++++++++++- .../components/light/blinksticklight.py | 11 +++++++++- homeassistant/components/light/demo.py | 10 +++++++++- homeassistant/components/light/enocean.py | 10 +++++++++- homeassistant/components/light/flux_led.py | 10 +++++++++- homeassistant/components/light/homematic.py | 10 +++++++++- homeassistant/components/light/hue.py | 13 +++++++++++- homeassistant/components/light/hyperion.py | 10 +++++++++- homeassistant/components/light/insteon_hub.py | 10 +++++++++- homeassistant/components/light/isy994.py | 16 +++++++++++++-- homeassistant/components/light/lifx.py | 12 ++++++++++- .../components/light/limitlessled.py | 20 ++++++++++++++++++- homeassistant/components/light/mqtt.py | 13 +++++++++++- homeassistant/components/light/mqtt_json.py | 6 +++++- homeassistant/components/light/mysensors.py | 10 +++++++++- .../components/light/osramlightify.py | 14 ++++++++++++- homeassistant/components/light/rfxtrx.py | 10 +++++++++- homeassistant/components/light/tellstick.py | 10 +++++++++- homeassistant/components/light/vera.py | 10 +++++++++- homeassistant/components/light/wemo.py | 11 +++++++++- homeassistant/components/light/wink.py | 10 +++++++++- homeassistant/components/light/x10.py | 10 +++++++++- homeassistant/components/light/zwave.py | 10 +++++++++- homeassistant/components/qwikswitch.py | 10 ++++++++-- 24 files changed, 250 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 2a87d2e88bb..23afa58b628 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -30,6 +30,16 @@ ENTITY_ID_ALL_LIGHTS = group.ENTITY_ID_FORMAT.format('all_lights') ENTITY_ID_FORMAT = DOMAIN + ".{}" +# Bitfield of features supported by the light entity +ATTR_SUPPORTED_FEATURES = 'supported_features' +SUPPORT_BRIGHTNESS = 1 +SUPPORT_COLOR_TEMP = 2 +SUPPORT_EFFECT = 4 +SUPPORT_FLASH = 8 +SUPPORT_RGB_COLOR = 16 +SUPPORT_TRANSITION = 32 +SUPPORT_XY_COLOR = 64 + # Integer that represents transition time in seconds to make change. ATTR_TRANSITION = "transition" @@ -63,6 +73,7 @@ PROP_TO_ATTR = { 'color_temp': ATTR_COLOR_TEMP, 'rgb_color': ATTR_RGB_COLOR, 'xy_color': ATTR_XY_COLOR, + 'supported_features': ATTR_SUPPORTED_FEATURES, } # Service call validation schemas @@ -279,7 +290,7 @@ class Light(ToggleEntity): if self.is_on: for prop, attr in PROP_TO_ATTR.items(): value = getattr(self, prop) - if value: + if value is not None: data[attr] = value if ATTR_RGB_COLOR not in data and ATTR_XY_COLOR in data and \ @@ -287,5 +298,12 @@ class Light(ToggleEntity): data[ATTR_RGB_COLOR] = color_util.color_xy_brightness_to_RGB( data[ATTR_XY_COLOR][0], data[ATTR_XY_COLOR][1], data[ATTR_BRIGHTNESS]) + else: + data[ATTR_SUPPORTED_FEATURES] = self.supported_features return data + + @property + def supported_features(self): + """Flag supported features.""" + return 0 diff --git a/homeassistant/components/light/blinksticklight.py b/homeassistant/components/light/blinksticklight.py index 9e42a41cb91..ad3bb2c6751 100644 --- a/homeassistant/components/light/blinksticklight.py +++ b/homeassistant/components/light/blinksticklight.py @@ -6,7 +6,8 @@ https://home-assistant.io/components/light.blinksticklight/ """ import logging -from homeassistant.components.light import ATTR_RGB_COLOR, Light +from homeassistant.components.light import (ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, + Light) _LOGGER = logging.getLogger(__name__) @@ -14,6 +15,9 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ["blinkstick==1.1.7"] +SUPPORT_BLINKSTICK = SUPPORT_RGB_COLOR + + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Add device specified by serial number.""" @@ -54,6 +58,11 @@ class BlinkStickLight(Light): """Check whether any of the LEDs colors are non-zero.""" return sum(self._rgb_color) > 0 + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_BLINKSTICK + def update(self): """Read back the device state.""" self._rgb_color = self._stick.get_color() diff --git a/homeassistant/components/light/demo.py b/homeassistant/components/light/demo.py index 96095c49a39..4eb0a61d983 100644 --- a/homeassistant/components/light/demo.py +++ b/homeassistant/components/light/demo.py @@ -7,7 +7,8 @@ https://home-assistant.io/components/demo/ import random from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, + SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) LIGHT_COLORS = [ [237, 224, 33], @@ -16,6 +17,8 @@ LIGHT_COLORS = [ LIGHT_TEMPS = [240, 380] +SUPPORT_DEMO = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup the demo light platform.""" @@ -68,6 +71,11 @@ class DemoLight(Light): """Return true if light is on.""" return self._state + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_DEMO + def turn_on(self, **kwargs): """Turn the light on.""" self._state = True diff --git a/homeassistant/components/light/enocean.py b/homeassistant/components/light/enocean.py index 2c9db86e662..6bd132202fc 100644 --- a/homeassistant/components/light/enocean.py +++ b/homeassistant/components/light/enocean.py @@ -7,7 +7,8 @@ https://home-assistant.io/components/light.enocean/ import logging import math -from homeassistant.components.light import Light, ATTR_BRIGHTNESS +from homeassistant.components.light import (Light, ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS) from homeassistant.const import CONF_NAME from homeassistant.components import enocean @@ -19,6 +20,8 @@ DEPENDENCIES = ["enocean"] CONF_ID = "id" CONF_SENDER_ID = "sender_id" +SUPPORT_ENOCEAN = SUPPORT_BRIGHTNESS + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the EnOcean light platform.""" @@ -61,6 +64,11 @@ class EnOceanLight(enocean.EnOceanDevice, Light): """If light is on.""" return self._on_state + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_ENOCEAN + def turn_on(self, **kwargs): """Turn the light source on or sets a specific dimmer value.""" brightness = kwargs.get(ATTR_BRIGHTNESS) diff --git a/homeassistant/components/light/flux_led.py b/homeassistant/components/light/flux_led.py index ed696b0654e..13a52fcb1a1 100644 --- a/homeassistant/components/light/flux_led.py +++ b/homeassistant/components/light/flux_led.py @@ -10,7 +10,8 @@ import socket import voluptuous as vol from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_RGB_COLOR, - Light) + SUPPORT_BRIGHTNESS, + SUPPORT_RGB_COLOR, Light) import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/Danielhiversen/flux_led/archive/0.6.zip' @@ -30,6 +31,8 @@ PLATFORM_SCHEMA = vol.Schema({ vol.Optional('automatic_add', default=False): cv.boolean, }, extra=vol.ALLOW_EXTRA) +SUPPORT_FLUX_LED = SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup the Flux lights.""" @@ -110,6 +113,11 @@ class FluxLight(Light): """Return the color property.""" return self._bulb.getRgb() + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_FLUX_LED + def turn_on(self, **kwargs): """Turn the specified or all lights on.""" if not self.is_on: diff --git a/homeassistant/components/light/homematic.py b/homeassistant/components/light/homematic.py index b7e0328a574..2e233e0e3ff 100644 --- a/homeassistant/components/light/homematic.py +++ b/homeassistant/components/light/homematic.py @@ -5,7 +5,8 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.homematic/ """ import logging -from homeassistant.components.light import (ATTR_BRIGHTNESS, Light) +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) from homeassistant.const import STATE_UNKNOWN import homeassistant.components.homematic as homematic @@ -13,6 +14,8 @@ _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['homematic'] +SUPPORT_HOMEMATIC = SUPPORT_BRIGHTNESS + def setup_platform(hass, config, add_callback_devices, discovery_info=None): """Setup the Homematic light platform.""" @@ -46,6 +49,11 @@ class HMLight(homematic.HMDevice, Light): except TypeError: return False + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_HOMEMATIC + def turn_on(self, **kwargs): """Turn the light on.""" if not self.available: diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index 1901af8ee4a..b818f4ee932 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -17,7 +17,9 @@ import homeassistant.util.color as color_util from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, EFFECT_COLORLOOP, EFFECT_RANDOM, - FLASH_LONG, FLASH_SHORT, Light) + FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, + SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, + SUPPORT_XY_COLOR, Light) from homeassistant.const import CONF_FILENAME, CONF_HOST, DEVICE_DEFAULT_NAME from homeassistant.loader import get_component @@ -27,6 +29,10 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) PHUE_CONFIG_FILE = "phue.conf" +SUPPORT_HUE = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT | + SUPPORT_FLASH | SUPPORT_RGB_COLOR | SUPPORT_TRANSITION | + SUPPORT_XY_COLOR) + # Map ip to request id for configuring _CONFIGURING = {} @@ -228,6 +234,11 @@ class HueLight(Light): else: return self.info['state']['reachable'] and self.info['state']['on'] + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_HUE + def turn_on(self, **kwargs): """Turn the specified or all lights on.""" command = {'on': True} diff --git a/homeassistant/components/light/hyperion.py b/homeassistant/components/light/hyperion.py index 8a03048d0bc..139edd9188e 100644 --- a/homeassistant/components/light/hyperion.py +++ b/homeassistant/components/light/hyperion.py @@ -8,12 +8,15 @@ import json import logging import socket -from homeassistant.components.light import ATTR_RGB_COLOR, Light +from homeassistant.components.light import (ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, + Light) from homeassistant.const import CONF_HOST _LOGGER = logging.getLogger(__name__) REQUIREMENTS = [] +SUPPORT_HYPERION = SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup a Hyperion server remote.""" @@ -53,6 +56,11 @@ class Hyperion(Light): """Return true if not black.""" return self._rgb_color != [0, 0, 0] + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_HYPERION + def turn_on(self, **kwargs): """Turn the lights on.""" if ATTR_RGB_COLOR in kwargs: diff --git a/homeassistant/components/light/insteon_hub.py b/homeassistant/components/light/insteon_hub.py index 4cfa6b25b06..70beadb6c1d 100644 --- a/homeassistant/components/light/insteon_hub.py +++ b/homeassistant/components/light/insteon_hub.py @@ -5,7 +5,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/insteon_hub/ """ from homeassistant.components.insteon_hub import INSTEON -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) + +SUPPORT_INSTEON_HUB = SUPPORT_BRIGHTNESS def setup_platform(hass, config, add_devices, discovery_info=None): @@ -55,6 +58,11 @@ class InsteonToggleDevice(Light): """Return the boolean response if the node is on.""" return self._value != 0 + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_INSTEON_HUB + def turn_on(self, **kwargs): """Turn device on.""" if ATTR_BRIGHTNESS in kwargs: diff --git a/homeassistant/components/light/isy994.py b/homeassistant/components/light/isy994.py index f7261540ddd..031fa7debb6 100644 --- a/homeassistant/components/light/isy994.py +++ b/homeassistant/components/light/isy994.py @@ -8,9 +8,13 @@ import logging from homeassistant.components.isy994 import ( HIDDEN_STRING, ISY, SENSOR_STRING, ISYDeviceABC) -from homeassistant.components.light import ATTR_BRIGHTNESS +from homeassistant.components.light import (ATTR_BRIGHTNESS, + ATTR_SUPPORTED_FEATURES, + SUPPORT_BRIGHTNESS) from homeassistant.const import STATE_OFF, STATE_ON +SUPPORT_ISY994 = SUPPORT_BRIGHTNESS + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the ISY994 platform.""" @@ -36,10 +40,18 @@ class ISYLightDevice(ISYDeviceABC): _domain = 'light' _dtype = 'analog' - _attrs = {ATTR_BRIGHTNESS: 'value'} + _attrs = { + ATTR_BRIGHTNESS: 'value', + ATTR_SUPPORTED_FEATURES: 'supported_features', + } _onattrs = [ATTR_BRIGHTNESS] _states = [STATE_ON, STATE_OFF] + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_ISY994 + def _attr_filter(self, attr): """Filter brightness out of entity while off.""" if ATTR_BRIGHTNESS in attr and not self.is_on: diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index e5b749037ad..39038fb0356 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -8,7 +8,9 @@ import colorsys import logging from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, + SUPPORT_TRANSITION, Light) from homeassistant.helpers.event import track_time_change _LOGGER = logging.getLogger(__name__) @@ -24,6 +26,9 @@ TEMP_MAX = 9000 # lifx maximum temperature TEMP_MIN_HASS = 154 # home assistant minimum temperature TEMP_MAX_HASS = 500 # home assistant maximum temperature +SUPPORT_LIFX = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR | + SUPPORT_TRANSITION) + class LIFX(): """Representation of a LIFX light.""" @@ -185,6 +190,11 @@ class LIFXLight(Light): _LOGGER.debug("is_on: %d", self._power) return self._power != 0 + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_LIFX + def turn_on(self, **kwargs): """Turn the device on.""" if ATTR_TRANSITION in kwargs: diff --git a/homeassistant/components/light/limitlessled.py b/homeassistant/components/light/limitlessled.py index 010088af824..aac28f9ced8 100644 --- a/homeassistant/components/light/limitlessled.py +++ b/homeassistant/components/light/limitlessled.py @@ -9,7 +9,9 @@ import logging from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, - ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG, Light) + ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, + SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light) _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['limitlessled==1.0.0'] @@ -20,6 +22,12 @@ DEFAULT_VERSION = 5 DEFAULT_LED_TYPE = 'rgbw' WHITE = [255, 255, 255] +SUPPORT_LIMITLESSLED_WHITE = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | + SUPPORT_TRANSITION) +SUPPORT_LIMITLESSLED_RGB = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | + SUPPORT_FLASH | SUPPORT_RGB_COLOR | + SUPPORT_TRANSITION) + def rewrite_legacy(config): """Rewrite legacy configuration to new format.""" @@ -168,6 +176,11 @@ class LimitlessLEDWhiteGroup(LimitlessLEDGroup): """Return the temperature property.""" return self._temperature + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_LIMITLESSLED_WHITE + @state(True) def turn_on(self, transition_time, pipeline, **kwargs): """Turn on (or adjust property of) a group.""" @@ -203,6 +216,11 @@ class LimitlessLEDRGBWGroup(LimitlessLEDGroup): """Return the color property.""" return self._color + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_LIMITLESSLED_RGB + @state(True) def turn_on(self, transition_time, pipeline, **kwargs): """Turn on (or adjust property of) a group.""" diff --git a/homeassistant/components/light/mqtt.py b/homeassistant/components/light/mqtt.py index 2d0e7bb6df0..ed8603a0ae8 100644 --- a/homeassistant/components/light/mqtt.py +++ b/homeassistant/components/light/mqtt.py @@ -11,7 +11,8 @@ import voluptuous as vol import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, + Light) from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE from homeassistant.components.mqtt import ( CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN) @@ -108,6 +109,11 @@ class MqttLight(Light): topic["brightness_state_topic"] is None) self._brightness_scale = brightness_scale self._state = False + self._supported_features = 0 + self._supported_features |= ( + topic['rgb_state_topic'] is not None and SUPPORT_RGB_COLOR) + self._supported_features |= ( + topic['brightness_state_topic'] is not None and SUPPORT_BRIGHTNESS) templates = {key: ((lambda value: value) if tpl is None else partial(render_with_possible_json_value, hass, tpl)) @@ -188,6 +194,11 @@ class MqttLight(Light): """Return true if we do optimistic updates.""" return self._optimistic + @property + def supported_features(self): + """Flag supported features.""" + return self._supported_features + def turn_on(self, **kwargs): """Turn the device on.""" should_update = False diff --git a/homeassistant/components/light/mqtt_json.py b/homeassistant/components/light/mqtt_json.py index 76db3fe9f0c..abc3c53f37f 100755 --- a/homeassistant/components/light/mqtt_json.py +++ b/homeassistant/components/light/mqtt_json.py @@ -12,7 +12,8 @@ import voluptuous as vol import homeassistant.components.mqtt as mqtt from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_RGB_COLOR, ATTR_TRANSITION, - ATTR_FLASH, FLASH_LONG, FLASH_SHORT, Light) + ATTR_FLASH, FLASH_LONG, FLASH_SHORT, SUPPORT_BRIGHTNESS, SUPPORT_FLASH, + SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light) from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_PLATFORM from homeassistant.components.mqtt import ( CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN) @@ -36,6 +37,9 @@ CONF_RGB = "rgb" CONF_FLASH_TIME_SHORT = "flash_time_short" CONF_FLASH_TIME_LONG = "flash_time_long" +SUPPORT_MQTT_JSON = (SUPPORT_BRIGHTNESS | SUPPORT_FLASH | SUPPORT_RGB_COLOR | + SUPPORT_TRANSITION) + # Stealing some of these from the base MQTT configs. PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): DOMAIN, diff --git a/homeassistant/components/light/mysensors.py b/homeassistant/components/light/mysensors.py index d8d288afd0e..434eb4f2f22 100644 --- a/homeassistant/components/light/mysensors.py +++ b/homeassistant/components/light/mysensors.py @@ -9,7 +9,8 @@ import logging from homeassistant.components import mysensors from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_RGB_COLOR, - Light) + SUPPORT_BRIGHTNESS, + SUPPORT_RGB_COLOR, Light) from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.util.color import rgb_hex_to_rgb_list @@ -18,6 +19,8 @@ ATTR_RGB_WHITE = 'rgb_white' ATTR_VALUE = 'value' ATTR_VALUE_TYPE = 'value_type' +SUPPORT_MYSENSORS = SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the mysensors platform for sensors.""" @@ -87,6 +90,11 @@ class MySensorsLight(mysensors.MySensorsDeviceEntity, Light): """Return true if device is on.""" return self._state + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_MYSENSORS + def _turn_on_light(self): """Turn on light child device.""" set_req = self.gateway.const.SetReq diff --git a/homeassistant/components/light/osramlightify.py b/homeassistant/components/light/osramlightify.py index 243d11116da..41a226031d6 100644 --- a/homeassistant/components/light/osramlightify.py +++ b/homeassistant/components/light/osramlightify.py @@ -15,7 +15,11 @@ from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, - ATTR_TRANSITION + ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, + SUPPORT_COLOR_TEMP, + SUPPORT_RGB_COLOR, + SUPPORT_TRANSITION, ) _LOGGER = logging.getLogger(__name__) @@ -28,6 +32,9 @@ TEMP_MAX_HASS = 500 # home assistant maximum temperature MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) +SUPPORT_OSRAMLIGHTIFY = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | + SUPPORT_RGB_COLOR | SUPPORT_TRANSITION) + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup Osram Lightify lights.""" @@ -114,6 +121,11 @@ class OsramLightifyLight(Light): self._light.name(), self._light.on()) return self._light.on() + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_OSRAMLIGHTIFY + def turn_on(self, **kwargs): """Turn the device on.""" brightness = 100 diff --git a/homeassistant/components/light/rfxtrx.py b/homeassistant/components/light/rfxtrx.py index 798dcc66010..f63a03c0534 100644 --- a/homeassistant/components/light/rfxtrx.py +++ b/homeassistant/components/light/rfxtrx.py @@ -7,7 +7,8 @@ https://home-assistant.io/components/light.rfxtrx/ import logging import homeassistant.components.rfxtrx as rfxtrx -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) DEPENDENCIES = ['rfxtrx'] @@ -15,6 +16,8 @@ _LOGGER = logging.getLogger(__name__) PLATFORM_SCHEMA = rfxtrx.DEFAULT_SCHEMA +SUPPORT_RFXTRX = SUPPORT_BRIGHTNESS + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup the RFXtrx platform.""" @@ -48,6 +51,11 @@ class RfxtrxLight(rfxtrx.RfxtrxDevice, Light): """Return the brightness of this light between 0..255.""" return self._brightness + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_RFXTRX + def turn_on(self, **kwargs): """Turn the light on.""" brightness = kwargs.get(ATTR_BRIGHTNESS) diff --git a/homeassistant/components/light/tellstick.py b/homeassistant/components/light/tellstick.py index 67d8c243ebc..3f9364a4cd5 100644 --- a/homeassistant/components/light/tellstick.py +++ b/homeassistant/components/light/tellstick.py @@ -7,13 +7,16 @@ https://home-assistant.io/components/light.tellstick/ import voluptuous as vol from homeassistant.components import tellstick -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) from homeassistant.components.tellstick import (DEFAULT_SIGNAL_REPETITIONS, ATTR_DISCOVER_DEVICES, ATTR_DISCOVER_CONFIG) PLATFORM_SCHEMA = vol.Schema({vol.Required("platform"): tellstick.DOMAIN}) +SUPPORT_TELLSTICK = SUPPORT_BRIGHTNESS + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): @@ -51,6 +54,11 @@ class TellstickLight(tellstick.TellstickDevice, Light): """Return the brightness of this light between 0..255.""" return self._brightness + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_TELLSTICK + def set_tellstick_state(self, last_command_sent, last_data_sent): """Update the internal representation of the switch.""" from tellcore.constants import TELLSTICK_TURNON, TELLSTICK_DIM diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 142ccbc5b22..9e169ce4412 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -6,7 +6,8 @@ https://home-assistant.io/components/light.vera/ """ import logging -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) from homeassistant.const import ( STATE_OFF, STATE_ON) from homeassistant.components.vera import ( @@ -16,6 +17,8 @@ DEPENDENCIES = ['vera'] _LOGGER = logging.getLogger(__name__) +SUPPORT_VERA = SUPPORT_BRIGHTNESS + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices_callback, discovery_info=None): @@ -38,6 +41,11 @@ class VeraLight(VeraDevice, Light): if self.vera_device.is_dimmable: return self.vera_device.get_brightness() + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_VERA + def turn_on(self, **kwargs): """Turn the light on.""" if ATTR_BRIGHTNESS in kwargs and self.vera_device.is_dimmable: diff --git a/homeassistant/components/light/wemo.py b/homeassistant/components/light/wemo.py index a4aa6686a17..e1f741f4c73 100644 --- a/homeassistant/components/light/wemo.py +++ b/homeassistant/components/light/wemo.py @@ -11,7 +11,8 @@ import homeassistant.util as util import homeassistant.util.color as color_util from homeassistant.components.light import ( Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, - ATTR_XY_COLOR) + ATTR_XY_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, + SUPPORT_TRANSITION, SUPPORT_XY_COLOR) DEPENDENCIES = ['wemo'] @@ -20,6 +21,9 @@ MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) _LOGGER = logging.getLogger(__name__) +SUPPORT_WEMO = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR | + SUPPORT_TRANSITION | SUPPORT_XY_COLOR) + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup WeMo bridges and register connected lights.""" @@ -96,6 +100,11 @@ class WemoLight(Light): """True if device is on.""" return self.device.state['onoff'] != 0 + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_WEMO + def turn_on(self, **kwargs): """Turn the light on.""" transitiontime = int(kwargs.get(ATTR_TRANSITION, 0)) diff --git a/homeassistant/components/light/wink.py b/homeassistant/components/light/wink.py index c4a4e1bee1b..39c7e9f1ae6 100644 --- a/homeassistant/components/light/wink.py +++ b/homeassistant/components/light/wink.py @@ -7,7 +7,8 @@ https://home-assistant.io/components/light.wink/ import logging from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, \ - Light, ATTR_RGB_COLOR + ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, \ + SUPPORT_RGB_COLOR, Light from homeassistant.components.wink import WinkDevice from homeassistant.const import CONF_ACCESS_TOKEN from homeassistant.util import color as color_util @@ -16,6 +17,8 @@ from homeassistant.util.color import \ REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +SUPPORT_WINK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup Wink lights.""" @@ -68,6 +71,11 @@ class WinkLight(WinkDevice, Light): return color_util.color_temperature_kelvin_to_mired( self.wink.color_temperature_kelvin()) + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_WINK + # pylint: disable=too-few-public-methods def turn_on(self, **kwargs): """Turn the switch on.""" diff --git a/homeassistant/components/light/x10.py b/homeassistant/components/light/x10.py index a689d7604ba..40f5dfa6b73 100644 --- a/homeassistant/components/light/x10.py +++ b/homeassistant/components/light/x10.py @@ -6,10 +6,13 @@ https://home-assistant.io/components/light.x10/ """ import logging from subprocess import check_output, CalledProcessError, STDOUT -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) _LOGGER = logging.getLogger(__name__) +SUPPORT_X10 = SUPPORT_BRIGHTNESS + def x10_command(command): """Execute X10 command and check output.""" @@ -64,6 +67,11 @@ class X10Light(Light): """Return true if light is on.""" return self._is_on + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_X10 + def turn_on(self, **kwargs): """Instruct the light to turn on.""" x10_command("on " + self._id) diff --git a/homeassistant/components/light/zwave.py b/homeassistant/components/light/zwave.py index 1be5aba1cda..49c4b5f8dd9 100644 --- a/homeassistant/components/light/zwave.py +++ b/homeassistant/components/light/zwave.py @@ -10,7 +10,8 @@ import logging # pylint: disable=import-error from threading import Timer from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, \ - ATTR_RGB_COLOR, DOMAIN, Light + ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, \ + SUPPORT_RGB_COLOR, DOMAIN, Light from homeassistant.components import zwave from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.util.color import HASS_COLOR_MAX, HASS_COLOR_MIN, \ @@ -41,6 +42,8 @@ TEMP_MID_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 2 + HASS_COLOR_MIN TEMP_WARM_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 3 * 2 + HASS_COLOR_MIN TEMP_COLD_HASS = (HASS_COLOR_MAX - HASS_COLOR_MIN) / 3 + HASS_COLOR_MIN +SUPPORT_ZWAVE = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR + def setup_platform(hass, config, add_devices, discovery_info=None): """Find and add Z-Wave lights.""" @@ -137,6 +140,11 @@ class ZwaveDimmer(zwave.ZWaveDeviceEntity, Light): """Return true if device is on.""" return self._state == STATE_ON + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_ZWAVE + def turn_on(self, **kwargs): """Turn the device on.""" if ATTR_BRIGHTNESS in kwargs: diff --git a/homeassistant/components/qwikswitch.py b/homeassistant/components/qwikswitch.py index a93328bc723..0519ac6f40d 100644 --- a/homeassistant/components/qwikswitch.py +++ b/homeassistant/components/qwikswitch.py @@ -10,7 +10,8 @@ import voluptuous as vol from homeassistant.const import (EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers.discovery import load_platform -from homeassistant.components.light import ATTR_BRIGHTNESS, Light +from homeassistant.components.light import (ATTR_BRIGHTNESS, + SUPPORT_BRIGHTNESS, Light) from homeassistant.components.switch import SwitchDevice DOMAIN = 'qwikswitch' @@ -29,6 +30,8 @@ CONFIG_SCHEMA = vol.Schema({ QSUSB = {} +SUPPORT_QWIKSWITCH = SUPPORT_BRIGHTNESS + class QSToggleEntity(object): """Representation of a Qwikswitch Entity. @@ -108,7 +111,10 @@ class QSSwitch(QSToggleEntity, SwitchDevice): class QSLight(QSToggleEntity, Light): """Light based on a Qwikswitch relay/dimmer module.""" - pass + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_QWIKSWITCH # pylint: disable=too-many-locals From a7f218f712099f3fc7e2eda4ae88ec558448785a Mon Sep 17 00:00:00 2001 From: Juggels Date: Tue, 16 Aug 2016 08:19:11 +0200 Subject: [PATCH 016/193] HP ILO component (#2844) * HP ILO component * HP ILO component * Add Onboard Administrator sensor * Add Onboard Administrator sensor * Add period to first line Fix D400 error on line 1 --- .coveragerc | 1 + homeassistant/components/sensor/hp_ilo.py | 170 ++++++++++++++++++++++ homeassistant/const.py | 1 + requirements_all.txt | 3 + 4 files changed, 175 insertions(+) create mode 100644 homeassistant/components/sensor/hp_ilo.py diff --git a/.coveragerc b/.coveragerc index 530d7832d81..922698f72ab 100644 --- a/.coveragerc +++ b/.coveragerc @@ -206,6 +206,7 @@ omit = homeassistant/components/sensor/google_travel_time.py homeassistant/components/sensor/gpsd.py homeassistant/components/sensor/gtfs.py + homeassistant/components/sensor/hp_ilo.py homeassistant/components/sensor/imap.py homeassistant/components/sensor/lastfm.py homeassistant/components/sensor/loopenergy.py diff --git a/homeassistant/components/sensor/hp_ilo.py b/homeassistant/components/sensor/hp_ilo.py new file mode 100644 index 00000000000..49586e45d50 --- /dev/null +++ b/homeassistant/components/sensor/hp_ilo.py @@ -0,0 +1,170 @@ +""" +Support for information from HP ILO sensors. + +This allows monitoring of HP server information +""" +import logging +from datetime import timedelta + +import voluptuous as vol +from homeassistant.const import ( + CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD, CONF_NAME, + CONF_MONITORED_VARIABLES, + STATE_ON, STATE_OFF) +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['python-hpilo==3.8'] +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'HP ILO' +DEFAULT_PORT = 443 + +# Each sensor is defined as follows: 'Descriptive name', 'python-ilo function' +SENSOR_TYPES = { + 'server_name': ['Server Name', 'get_server_name'], + 'server_fqdn': ['Server FQDN', 'get_server_fqdn'], + 'server_host_data': ['Server Host Data', 'get_host_data'], + 'server_oa_info': ['Server Onboard Administrator Info', 'get_oa_info'], + 'server_power_status': ['Server Power state', 'get_host_power_status'], + 'server_power_readings': ['Server Power readings', 'get_power_readings'], + 'server_power_on_time': ['Server Power On time', + 'get_server_power_on_time'], + 'server_asset_tag': ['Server Asset Tag', 'get_asset_tag'], + 'server_uid_status': ['Server UID light', 'get_uid_status'], + 'server_health': ['Server Health', 'get_embedded_health'], + 'network_settings': ['Network Settings', 'get_network_settings'] +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_MONITORED_VARIABLES, default=['server_name']): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.positive_int, +}) + +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the HP ILO sensor.""" + hostname = config.get(CONF_HOST) + port = config.get(CONF_PORT) + login = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + monitored_variables = config.get(CONF_MONITORED_VARIABLES) + name = config.get(CONF_NAME) + + # Create a data fetcher to support all of the configured sensors. Then make + # the first call to init the data and confirm we can connect. + try: + hp_ilo_data = HpIloData(hostname, port, login, password) + except ValueError as error: + _LOGGER.error(error) + return False + + # Initialize and add all of the sensors. + devices = [] + for ilo_type in monitored_variables: + new_device = HpIloSensor(hp_ilo_data=hp_ilo_data, + sensor_type=SENSOR_TYPES.get(ilo_type), + client_name=name) + devices.append(new_device) + + add_devices(devices) + + +class HpIloSensor(Entity): + """Represents an HP ILO sensor.""" + + def __init__(self, hp_ilo_data, sensor_type, client_name): + """Initialize the sensor.""" + self._name = '{} {}'.format(client_name, sensor_type[0]) + self._ilo_function = sensor_type[1] + self.client_name = client_name + self.hp_ilo_data = hp_ilo_data + + self._state = None + self._data = None + + self.update() + + _LOGGER.debug("Created HP ILO sensor %r", self) + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def state_attributes(self): + """Return the state attributes.""" + return self._data + + def update(self): + """Get the latest data from HP ILO and updates the states.""" + # Call the API for new data. Each sensor will re-trigger this + # same exact call, but that's fine. Results should be cached for + # a short period of time to prevent hitting API limits. + self.hp_ilo_data.update() + ilo_data = getattr(self.hp_ilo_data.data, self._ilo_function)() + + # Store the data received from the ILO API + if isinstance(ilo_data, dict): + self._data = ilo_data + else: + self._data = {'value': ilo_data} + + # If the data received is an integer or string, store it as + # the sensor state + if isinstance(ilo_data, (str, bytes)): + states = [STATE_ON, STATE_OFF] + try: + index_element = states.index(str(ilo_data).lower()) + self._state = states[index_element] + except ValueError: + self._state = ilo_data + elif isinstance(ilo_data, (int, float)): + self._state = ilo_data + + +# pylint: disable=too-few-public-methods +class HpIloData(object): + """Gets the latest data from HP ILO.""" + + def __init__(self, host, port, login, password): + """Initialize the data object.""" + self._host = host + self._port = port + self._login = login + self._password = password + + self.data = None + + self.update() + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from HP ILO.""" + import hpilo + + try: + self.data = hpilo.Ilo(hostname=self._host, + login=self._login, + password=self._password, + port=self._port) + except (hpilo.IloError, hpilo.IloCommunicationError, + hpilo.IloLoginFailed) as error: + raise ValueError("Unable to init HP ILO. - %s", error) diff --git a/homeassistant/const.py b/homeassistant/const.py index 50055c98706..65ff03b5276 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -40,6 +40,7 @@ CONF_ICON = 'icon' CONF_LATITUDE = 'latitude' CONF_LONGITUDE = 'longitude' CONF_MONITORED_CONDITIONS = 'monitored_conditions' +CONF_MONITORED_VARIABLES = 'monitored_variables' CONF_NAME = 'name' CONF_OFFSET = 'offset' CONF_OPTIMISTIC = 'optimistic' diff --git a/requirements_all.txt b/requirements_all.txt index d4612f5c024..8d342853f21 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -336,6 +336,9 @@ pysnmp==4.3.2 # homeassistant.components.sensor.forecast python-forecastio==1.3.4 +# homeassistant.components.sensor.hp_ilo +python-hpilo==3.8 + # homeassistant.components.lirc # python-lirc==1.2.1 From 83a043a0ea90b377c9e6c299aac1c95280852357 Mon Sep 17 00:00:00 2001 From: David Straub Date: Tue, 16 Aug 2016 08:22:54 +0200 Subject: [PATCH 017/193] Add FritzBox call monitor sensor (#2791) * Add FritzBox call monitor sensor * Correct docstrings and suppress too few public methods warning * Remove blank lines after docstrings * Add blank lines after class docstrings * Remove trailing white space * Make daemon; add reconnect on disconnect --- .coveragerc | 1 + .../components/sensor/fritzbox_callmonitor.py | 160 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 homeassistant/components/sensor/fritzbox_callmonitor.py diff --git a/.coveragerc b/.coveragerc index 922698f72ab..9c8a4695537 100644 --- a/.coveragerc +++ b/.coveragerc @@ -202,6 +202,7 @@ omit = 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 homeassistant/components/sensor/gpsd.py diff --git a/homeassistant/components/sensor/fritzbox_callmonitor.py b/homeassistant/components/sensor/fritzbox_callmonitor.py new file mode 100644 index 00000000000..7525e5fcc81 --- /dev/null +++ b/homeassistant/components/sensor/fritzbox_callmonitor.py @@ -0,0 +1,160 @@ +""" +A sensor to monitor incoming and outgoing phone calls on a Fritz!Box router. + +To activate the call monitor on your Fritz!Box, dial #96*5* from any phone +connected to it. +""" +import logging +import socket +import threading +import datetime +import time +from homeassistant.helpers.entity import Entity + +_LOGGER = logging.getLogger(__name__) +DEFAULT_NAME = 'Phone' +DEFAULT_HOST = '169.254.1.1' # IP valid for all Fritz!Box routers +DEFAULT_PORT = 1012 +# sensor values +VALUE_DEFAULT = 'idle' # initial value +VALUE_RING = 'ringing' +VALUE_CALL = 'dialing' +VALUE_CONNECT = 'talking' +VALUE_DISCONNECT = 'idle' +INTERVAL_RECONNECT = 60 + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup Fritz!Box call monitor sensor platform.""" + host = config.get('host', DEFAULT_HOST) + port = config.get('port', DEFAULT_PORT) + + sensor = FritzBoxCallSensor(name=config.get('name', DEFAULT_NAME)) + + add_devices([sensor]) + + monitor = FritzBoxCallMonitor(host=host, port=port, sensor=sensor) + monitor.connect() + + if monitor.sock is None: + return False + else: + return True + + +# pylint: disable=too-few-public-methods +class FritzBoxCallSensor(Entity): + """Implementation of a Fritz!Box call monitor.""" + + def __init__(self, name): + """Initialize the sensor.""" + self._state = VALUE_DEFAULT + self._attributes = {} + self._name = name + + def set_state(self, state): + """Set the state.""" + self._state = state + + def set_attributes(self, attributes): + """Set the state attributes.""" + self._attributes = attributes + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return self._attributes + + +# pylint: disable=too-few-public-methods +class FritzBoxCallMonitor(object): + """Event listener to monitor calls on the Fritz!Box.""" + + def __init__(self, host, port, sensor): + """Initialize Fritz!Box monitor instance.""" + self.host = host + self.port = port + self.sock = None + self._sensor = sensor + + def connect(self): + """Connect to the Fritz!Box.""" + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(10) + try: + self.sock.connect((self.host, self.port)) + threading.Thread(target=self._listen, daemon=True).start() + except socket.error as err: + self.sock = None + _LOGGER.error("Cannot connect to %s on port %s: %s", + self.host, self.port, err) + + def _listen(self): + """Listen to incoming or outgoing calls.""" + while True: + try: + response = self.sock.recv(2048) + except socket.timeout: + # if no response after 10 seconds, just recv again + continue + response = str(response, "utf-8") + + if not response: + # if the response is empty, the connection has been lost. + # try to reconnect + self.sock = None + while self.sock is None: + self.connect() + time.sleep(INTERVAL_RECONNECT) + else: + line = response.split("\n", 1)[0] + self._parse(line) + time.sleep(1) + return + + def _parse(self, line): + """Parse the call information and set the sensor states.""" + line = line.split(";") + df_in = "%d.%m.%y %H:%M:%S" + df_out = "%Y-%m-%dT%H:%M:%S" + isotime = datetime.datetime.strptime(line[0], df_in).strftime(df_out) + if line[1] == "RING": + self._sensor.set_state(VALUE_RING) + att = {"type": "incoming", + "from": line[3], + "to": line[4], + "device": line[5], + "initiated": isotime} + self._sensor.set_attributes(att) + elif line[1] == "CALL": + self._sensor.set_state(VALUE_CALL) + att = {"type": "outgoing", + "from": line[4], + "to": line[5], + "device": line[6], + "initiated": isotime} + self._sensor.set_attributes(att) + elif line[1] == "CONNECT": + self._sensor.set_state(VALUE_CONNECT) + att = {"with": line[4], "device": [3], "accepted": isotime} + self._sensor.set_attributes(att) + elif line[1] == "DISCONNECT": + self._sensor.set_state(VALUE_DISCONNECT) + att = {"duration": line[3], "closed": isotime} + self._sensor.set_attributes(att) + self._sensor.update_ha_state() From 693098ff00c98a9afccc27e74c80f515f1b42d0c Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Tue, 16 Aug 2016 08:42:45 +0200 Subject: [PATCH 018/193] Bugfix in pknx library (#2835) * Bugfix in pknx library * Version pinned to 0.3.3 --- homeassistant/components/knx.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/knx.py b/homeassistant/components/knx.py index 763b9d81ded..ec837cbf7b6 100644 --- a/homeassistant/components/knx.py +++ b/homeassistant/components/knx.py @@ -10,7 +10,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.helpers.entity import Entity DOMAIN = "knx" -REQUIREMENTS = ['knxip==0.3.2'] +REQUIREMENTS = ['knxip==0.3.3'] EVENT_KNX_FRAME_RECEIVED = "knx_frame_received" diff --git a/requirements_all.txt b/requirements_all.txt index 8d342853f21..26a4afdeb63 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -197,7 +197,7 @@ insteon_hub==0.4.5 jsonrpc-requests==0.3 # homeassistant.components.knx -knxip==0.3.2 +knxip==0.3.3 # homeassistant.components.light.lifx liffylights==0.9.4 From 7762365b3ff5c0762640f5326a8ad5d84416f486 Mon Sep 17 00:00:00 2001 From: Nuno Sousa Date: Tue, 16 Aug 2016 08:37:58 +0100 Subject: [PATCH 019/193] Add position to zwave rollershutter (#2772) --- .../components/rollershutter/__init__.py | 25 ++++++++- .../components/rollershutter/command_line.py | 1 + .../components/rollershutter/demo.py | 8 +++ .../components/rollershutter/homematic.py | 1 + .../components/rollershutter/mqtt.py | 1 + .../components/rollershutter/rfxtrx.py | 1 + .../components/rollershutter/scsgate.py | 1 + .../components/rollershutter/services.yaml | 8 +++ .../components/rollershutter/wink.py | 1 + .../components/rollershutter/zwave.py | 4 ++ homeassistant/const.py | 1 + tests/components/rollershutter/test_demo.py | 55 +++++++++++++++++++ 12 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/components/rollershutter/test_demo.py diff --git a/homeassistant/components/rollershutter/__init__.py b/homeassistant/components/rollershutter/__init__.py index c5fcb594f31..7d8b8235ed6 100644 --- a/homeassistant/components/rollershutter/__init__.py +++ b/homeassistant/components/rollershutter/__init__.py @@ -16,7 +16,7 @@ from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa import homeassistant.helpers.config_validation as cv from homeassistant.components import group from homeassistant.const import ( - SERVICE_MOVE_UP, SERVICE_MOVE_DOWN, SERVICE_STOP, + SERVICE_MOVE_UP, SERVICE_MOVE_DOWN, SERVICE_MOVE_POSITION, SERVICE_STOP, STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN, ATTR_ENTITY_ID) @@ -32,11 +32,17 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}' _LOGGER = logging.getLogger(__name__) ATTR_CURRENT_POSITION = 'current_position' +ATTR_POSITION = 'position' ROLLERSHUTTER_SERVICE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, }) +ROLLERSHUTTER_MOVE_POSITION_SCHEMA = ROLLERSHUTTER_SERVICE_SCHEMA.extend({ + vol.Required(ATTR_POSITION): + vol.All(vol.Coerce(int), vol.Range(min=0, max=100)), +}) + def is_open(hass, entity_id=None): """Return if the roller shutter is open based on the statemachine.""" @@ -56,6 +62,13 @@ def move_down(hass, entity_id=None): hass.services.call(DOMAIN, SERVICE_MOVE_DOWN, data) +def move_position(hass, position, entity_id=None): + """Move to specific position all or specified roller shutter.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} + data[ATTR_POSITION] = position + hass.services.call(DOMAIN, SERVICE_MOVE_POSITION, data) + + def stop(hass, entity_id=None): """Stop all or specified roller shutter.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None @@ -77,6 +90,8 @@ def setup(hass, config): rollershutter.move_up() elif service.service == SERVICE_MOVE_DOWN: rollershutter.move_down() + elif service.service == SERVICE_MOVE_POSITION: + rollershutter.move_position(service.data[ATTR_POSITION]) elif service.service == SERVICE_STOP: rollershutter.stop() @@ -94,6 +109,10 @@ def setup(hass, config): handle_rollershutter_service, descriptions.get(SERVICE_MOVE_DOWN), schema=ROLLERSHUTTER_SERVICE_SCHEMA) + hass.services.register(DOMAIN, SERVICE_MOVE_POSITION, + handle_rollershutter_service, + descriptions.get(SERVICE_MOVE_POSITION), + schema=ROLLERSHUTTER_MOVE_POSITION_SCHEMA) hass.services.register(DOMAIN, SERVICE_STOP, handle_rollershutter_service, descriptions.get(SERVICE_STOP), @@ -143,6 +162,10 @@ class RollershutterDevice(Entity): """Move the roller shutter up.""" raise NotImplementedError() + def move_position(self, **kwargs): + """Move the roller shutter to a specific position.""" + raise NotImplementedError() + def stop(self, **kwargs): """Stop the roller shutter.""" raise NotImplementedError() diff --git a/homeassistant/components/rollershutter/command_line.py b/homeassistant/components/rollershutter/command_line.py index c90a8be9410..976992e0061 100644 --- a/homeassistant/components/rollershutter/command_line.py +++ b/homeassistant/components/rollershutter/command_line.py @@ -32,6 +32,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): add_devices_callback(devices) +# pylint: disable=abstract-method # pylint: disable=too-many-arguments, too-many-instance-attributes class CommandRollershutter(RollershutterDevice): """Representation a command line roller shutter.""" diff --git a/homeassistant/components/rollershutter/demo.py b/homeassistant/components/rollershutter/demo.py index ebdc3907a59..31915019c5e 100644 --- a/homeassistant/components/rollershutter/demo.py +++ b/homeassistant/components/rollershutter/demo.py @@ -60,6 +60,14 @@ class DemoRollershutter(RollershutterDevice): self._listen() self._moving_up = False + def move_position(self, position, **kwargs): + """Move the roller shutter to a specific position.""" + if self._position == position: + return + + self._listen() + self._moving_up = position < self._position + def stop(self, **kwargs): """Stop the roller shutter.""" if self._listener is not None: diff --git a/homeassistant/components/rollershutter/homematic.py b/homeassistant/components/rollershutter/homematic.py index 9bdad7ee68c..805c5dceb82 100644 --- a/homeassistant/components/rollershutter/homematic.py +++ b/homeassistant/components/rollershutter/homematic.py @@ -30,6 +30,7 @@ def setup_platform(hass, config, add_callback_devices, discovery_info=None): add_callback_devices) +# pylint: disable=abstract-method class HMRollershutter(homematic.HMDevice, RollershutterDevice): """Represents a Homematic Rollershutter in Home Assistant.""" diff --git a/homeassistant/components/rollershutter/mqtt.py b/homeassistant/components/rollershutter/mqtt.py index 6465c02dca2..d0183da7a0f 100644 --- a/homeassistant/components/rollershutter/mqtt.py +++ b/homeassistant/components/rollershutter/mqtt.py @@ -52,6 +52,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): )]) +# pylint: disable=abstract-method # pylint: disable=too-many-arguments, too-many-instance-attributes class MqttRollershutter(RollershutterDevice): """Representation of a roller shutter that can be controlled using MQTT.""" diff --git a/homeassistant/components/rollershutter/rfxtrx.py b/homeassistant/components/rollershutter/rfxtrx.py index 18a2844b19c..19bcea4e892 100644 --- a/homeassistant/components/rollershutter/rfxtrx.py +++ b/homeassistant/components/rollershutter/rfxtrx.py @@ -40,6 +40,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(rollershutter_update) +# pylint: disable=abstract-method class RfxtrxRollershutter(rfxtrx.RfxtrxDevice, RollershutterDevice): """Representation of an rfxtrx roller shutter.""" diff --git a/homeassistant/components/rollershutter/scsgate.py b/homeassistant/components/rollershutter/scsgate.py index 078173e1924..e67395d054c 100644 --- a/homeassistant/components/rollershutter/scsgate.py +++ b/homeassistant/components/rollershutter/scsgate.py @@ -37,6 +37,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): add_devices_callback(rollershutters) +# pylint: disable=abstract-method # pylint: disable=too-many-arguments, too-many-instance-attributes class SCSGateRollerShutter(RollershutterDevice): """Representation of SCSGate rollershutter.""" diff --git a/homeassistant/components/rollershutter/services.yaml b/homeassistant/components/rollershutter/services.yaml index b7ef0a17643..2991693961b 100644 --- a/homeassistant/components/rollershutter/services.yaml +++ b/homeassistant/components/rollershutter/services.yaml @@ -14,6 +14,14 @@ move_down: description: Name(s) of roller shutter(s) to move down example: 'rollershutter.living_room' +move_position: + description: Move to specific position all or specified roller shutter + + fields: + position: + description: Position of the rollershutter (0 to 100) + example: 30 + stop: description: Stop all or specified roller shutter diff --git a/homeassistant/components/rollershutter/wink.py b/homeassistant/components/rollershutter/wink.py index 8a791ea9b97..e18a75082a7 100644 --- a/homeassistant/components/rollershutter/wink.py +++ b/homeassistant/components/rollershutter/wink.py @@ -32,6 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): pywink.get_shades()) +# pylint: disable=abstract-method class WinkRollershutterDevice(WinkDevice, RollershutterDevice): """Representation of a Wink rollershutter (shades).""" diff --git a/homeassistant/components/rollershutter/zwave.py b/homeassistant/components/rollershutter/zwave.py index 01d6980a795..efe93b3db79 100644 --- a/homeassistant/components/rollershutter/zwave.py +++ b/homeassistant/components/rollershutter/zwave.py @@ -97,6 +97,10 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice): self._lozwmgr.pressButton(value.value_id) break + def move_position(self, position, **kwargs): + """Move the roller shutter to a specific position.""" + self._node.set_dimmer(self._value.value_id, 100 - position) + def stop(self, **kwargs): """Stop the roller shutter.""" for value in self._node.get_values( diff --git a/homeassistant/const.py b/homeassistant/const.py index 65ff03b5276..61de02041b2 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -221,6 +221,7 @@ SERVICE_CLOSE = "close" SERVICE_MOVE_UP = 'move_up' SERVICE_MOVE_DOWN = 'move_down' +SERVICE_MOVE_POSITION = 'move_position' SERVICE_STOP = 'stop' # #### API / REMOTE #### diff --git a/tests/components/rollershutter/test_demo.py b/tests/components/rollershutter/test_demo.py new file mode 100644 index 00000000000..039221fad6e --- /dev/null +++ b/tests/components/rollershutter/test_demo.py @@ -0,0 +1,55 @@ +"""The tests for the Demo roller shutter platform.""" +import unittest +import homeassistant.util.dt as dt_util + +from homeassistant.components.rollershutter import demo +from tests.common import fire_time_changed, get_test_home_assistant + + +class TestRollershutterDemo(unittest.TestCase): + """Test the Demo roller shutter.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_move_up(self): + """Test moving the rollershutter up.""" + entity = demo.DemoRollershutter(self.hass, 'test', 100) + entity.move_up() + + fire_time_changed(self.hass, dt_util.utcnow()) + self.hass.pool.block_till_done() + self.assertEqual(90, entity.current_position) + + def test_move_down(self): + """Test moving the rollershutter down.""" + entity = demo.DemoRollershutter(self.hass, 'test', 0) + entity.move_down() + + fire_time_changed(self.hass, dt_util.utcnow()) + self.hass.pool.block_till_done() + self.assertEqual(10, entity.current_position) + + def test_move_position(self): + """Test moving the rollershutter to a specific position.""" + entity = demo.DemoRollershutter(self.hass, 'test', 0) + entity.move_position(10) + + fire_time_changed(self.hass, dt_util.utcnow()) + self.hass.pool.block_till_done() + self.assertEqual(10, entity.current_position) + + def test_stop(self): + """Test stopping the rollershutter.""" + entity = demo.DemoRollershutter(self.hass, 'test', 0) + entity.move_down() + entity.stop() + + fire_time_changed(self.hass, dt_util.utcnow()) + self.hass.pool.block_till_done() + self.assertEqual(0, entity.current_position) From 41dad9a8f74ca9ef7cda86e102ba2b947e459266 Mon Sep 17 00:00:00 2001 From: pavoni Date: Tue, 16 Aug 2016 09:48:13 +0100 Subject: [PATCH 020/193] Tidy warnings. --- .../components/device_tracker/owntracks.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index 869728f67f9..cdb1f90ba8a 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -54,14 +54,14 @@ def setup_scanner(hass, config, see): return data if max_gps_accuracy is not None and \ convert(data.get('acc'), float, 0.0) > max_gps_accuracy: - _LOGGER.debug('Skipping %s update because expected GPS ' - 'accuracy %s is not met: %s', - data_type, max_gps_accuracy, data) + _LOGGER.warning('Ignoring %s update because expected GPS ' + 'accuracy %s is not met: %s', + data_type, max_gps_accuracy, payload) return None if convert(data.get('acc'), float, 1.0) == 0.0: - _LOGGER.debug('Skipping %s update because GPS accuracy' - 'is zero', - data_type) + _LOGGER.warning('Ignoring %s update because GPS accuracy' + 'is zero: %s', + data_type, payload) return None return data @@ -152,17 +152,20 @@ def setup_scanner(hass, config, see): if 'acc' in data: if data['acc'] == 0.0: valid_gps = False - _LOGGER.info("Zero GPS reported") + _LOGGER.warning( + 'Ignoring GPS in region exit because accuracy' + 'is zero: %s', + payload) if (max_gps_accuracy is not None and data['acc'] > max_gps_accuracy): valid_gps = False - _LOGGER.info("Inaccurate GPS reported") - + _LOGGER.warning( + 'Ignoring GPS in region exit because expected ' + 'GPS accuracy %s is not met: %s', + max_gps_accuracy, payload) if valid_gps: see(**kwargs) see_beacons(dev_id, kwargs) - else: - _LOGGER.info("Inaccurate GPS reported") beacons = MOBILE_BEACONS_ACTIVE[dev_id] if location in beacons: From 1c140de0dcdc446f54f10055b51767efadf25663 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 16 Aug 2016 21:42:43 +0200 Subject: [PATCH 021/193] Use voluptuous for NZB sensors (#2847) --- homeassistant/components/sensor/nzbget.py | 196 +++++++++++---------- homeassistant/components/sensor/sabnzbd.py | 60 ++++--- 2 files changed, 145 insertions(+), 111 deletions(-) diff --git a/homeassistant/components/sensor/nzbget.py b/homeassistant/components/sensor/nzbget.py index 874005cebca..6248b935c95 100644 --- a/homeassistant/components/sensor/nzbget.py +++ b/homeassistant/components/sensor/nzbget.py @@ -1,48 +1,65 @@ """ -Support for monitoring NZBGet nzb client. +Support for monitoring NZBGet NZB client. -Uses NZBGet's JSON-RPC API to query for monitored variables. +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.nzbget/ """ import logging from datetime import timedelta -import requests +import requests +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_NAME, CONF_PORT, + CONTENT_TYPE_JSON, CONF_MONITORED_VARIABLES) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv + +DEFAULT_NAME = 'NZBGet' +DEFAULT_PORT = 6789 -REQUIREMENTS = [] SENSOR_TYPES = { - "ArticleCacheMB": ("Article Cache", "MB"), - "AverageDownloadRate": ("Average Speed", "MB/s"), - "DownloadRate": ("Speed", "MB/s"), - "DownloadPaused": ("Download Paused", None), - "FreeDiskSpaceMB": ("Disk Free", "MB"), - "PostPaused": ("Post Processing Paused", None), - "RemainingSizeMB": ("Queue Size", "MB"), + 'article_cache': ['ArticleCacheMB', 'Article Cache', 'MB'], + 'average_download_rate': ['AverageDownloadRate', 'Average Speed', 'MB/s'], + 'download_paused': ['DownloadPaused', 'Download Paused', None], + 'download_rate': ['DownloadRate', 'Speed', 'MB/s'], + 'download_size': ['DownloadedSizeMB', 'Size', 'MB'], + 'free_disk_space': ['FreeDiskSpaceMB', 'Disk Free', 'MB'], + 'post_paused': ['PostPaused', 'Post Processing Paused', None], + 'remaining_size': ['RemainingSizeMB', 'Queue Size', 'MB'], + 'uptime': ['UpTimeSec', 'Uptime', 'min'], } -DEFAULT_TYPES = [ - "DownloadRate", - "DownloadPaused", - "RemainingSizeMB", -] + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_MONITORED_VARIABLES, default=['download_rate']): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.string, + vol.Optional(CONF_USERNAME): cv.string, +}) _LOGGER = logging.getLogger(__name__) +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) -# pylint: disable=unused-argument + +# pylint: disable=unused-argument, too-many-locals def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up nzbget sensors.""" - base_url = config.get("base_url") - name = config.get("name", "NZBGet") - username = config.get("username") - password = config.get("password") - monitored_types = config.get("monitored_variables", DEFAULT_TYPES) + """Setup the NZBGet sensors.""" + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + name = config.get(CONF_NAME) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + monitored_types = config.get(CONF_MONITORED_VARIABLES) - if not base_url: - _LOGGER.error("Missing base_url config for NzbGet") - return False - - url = "{}/jsonrpc".format(base_url) + url = "http://{}:{}/jsonrpc".format(host, port) try: nzbgetapi = NZBGetAPI(api_url=url, @@ -51,78 +68,32 @@ def setup_platform(hass, config, add_devices, discovery_info=None): nzbgetapi.update() except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as conn_err: - _LOGGER.error("Error setting up NZBGet API: %r", conn_err) + _LOGGER.error("Error setting up NZBGet API: %s", conn_err) return False devices = [] for ng_type in monitored_types: - if ng_type in SENSOR_TYPES: - new_sensor = NZBGetSensor(api=nzbgetapi, - sensor_type=ng_type, - client_name=name) - devices.append(new_sensor) - else: - _LOGGER.error("Unknown nzbget sensor type: %s", ng_type) + new_sensor = NZBGetSensor(api=nzbgetapi, + sensor_type=SENSOR_TYPES.get(ng_type), + client_name=name) + devices.append(new_sensor) + add_devices(devices) -class NZBGetAPI(object): - """Simple json-rpc wrapper for nzbget's api.""" - - def __init__(self, api_url, username=None, password=None): - """Initialize NZBGet API and set headers needed later.""" - self.api_url = api_url - self.status = None - self.headers = {'content-type': 'application/json'} - if username is not None and password is not None: - self.auth = (username, password) - else: - self.auth = None - # set the intial state - self.update() - - def post(self, method, params=None): - """Send a post request, and return the response as a dict.""" - payload = {"method": method} - if params: - payload['params'] = params - try: - response = requests.post(self.api_url, - json=payload, - auth=self.auth, - headers=self.headers, - timeout=30) - response.raise_for_status() - return response.json() - except requests.exceptions.ConnectionError as conn_exc: - _LOGGER.error("Failed to update nzbget status from %s. Error: %s", - self.api_url, conn_exc) - raise - - @Throttle(timedelta(seconds=5)) - def update(self): - """Update cached response.""" - try: - self.status = self.post('status')['result'] - except requests.exceptions.ConnectionError: - # failed to update status - exception already logged in self.post - raise - - class NZBGetSensor(Entity): - """Represents an NZBGet sensor.""" + """Representation of a NZBGet sensor.""" def __init__(self, api, sensor_type, client_name): """Initialize a new NZBGet sensor.""" - self._name = client_name + ' ' + SENSOR_TYPES[sensor_type][0] - self.type = sensor_type + self._name = '{} {}'.format(client_name, sensor_type[1]) + self.type = sensor_type[0] self.client_name = client_name self.api = api self._state = None - self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] - # Set initial state + self._unit_of_measurement = sensor_type[2] self.update() - _LOGGER.debug("created nzbget sensor %r", self) + _LOGGER.debug("Created NZBGet sensor: %s", self.type) @property def name(self): @@ -144,21 +115,68 @@ class NZBGetSensor(Entity): try: self.api.update() except requests.exceptions.ConnectionError: - # Error calling the api, already logged in api.update() + # Error calling the API, already logged in api.update() return if self.api.status is None: - _LOGGER.debug("update of %s requested, but no status is available", + _LOGGER.debug("Update of %s requested, but no status is available", self._name) return value = self.api.status.get(self.type) if value is None: - _LOGGER.warning("unable to locate value for %s", self.type) + _LOGGER.warning("Unable to locate value for %s", self.type) return if "DownloadRate" in self.type and value > 0: # Convert download rate from Bytes/s to MBytes/s - self._state = round(value / 1024 / 1024, 2) + self._state = round(value / 2**20, 2) + elif "UpTimeSec" in self.type and value > 0: + # Convert uptime from seconds to minutes + self._state = round(value / 60, 2) else: self._state = value + + +class NZBGetAPI(object): + """Simple JSON-RPC wrapper for NZBGet's API.""" + + def __init__(self, api_url, username=None, password=None): + """Initialize NZBGet API and set headers needed later.""" + self.api_url = api_url + self.status = None + self.headers = {'content-type': CONTENT_TYPE_JSON} + + if username is not None and password is not None: + self.auth = (username, password) + else: + self.auth = None + self.update() + + def post(self, method, params=None): + """Send a POST request and return the response as a dict.""" + payload = {"method": method} + + if params: + payload['params'] = params + try: + response = requests.post(self.api_url, + json=payload, + auth=self.auth, + headers=self.headers, + timeout=5) + response.raise_for_status() + return response.json() + except requests.exceptions.ConnectionError as conn_exc: + _LOGGER.error("Failed to update NZBGet status from %s. Error: %s", + self.api_url, conn_exc) + raise + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Update cached response.""" + try: + self.status = self.post('status')['result'] + except requests.exceptions.ConnectionError: + # failed to update status - exception already logged in self.post + raise diff --git a/homeassistant/components/sensor/sabnzbd.py b/homeassistant/components/sensor/sabnzbd.py index 65a217930dc..48440f66790 100644 --- a/homeassistant/components/sensor/sabnzbd.py +++ b/homeassistant/components/sensor/sabnzbd.py @@ -7,13 +7,22 @@ https://home-assistant.io/components/sensor.sabnzbd/ import logging from datetime import timedelta +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_HOST, CONF_API_KEY, CONF_NAME, CONF_PORT, CONF_MONITORED_VARIABLES) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' 'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip' '#python-sabnzbd==0.1'] +DEFAULT_NAME = 'SABnzbd' +DEFAULT_PORT = 8080 + SENSOR_TYPES = { 'current_status': ['Status', None], 'speed': ['Speed', 'MB/s'], @@ -23,45 +32,52 @@ SENSOR_TYPES = { 'disk_free': ['Disk Free', 'GB'], } +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_MONITORED_VARIABLES, default=['current_status']): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.string, +}) + _LOGGER = logging.getLogger(__name__) _THROTTLED_REFRESH = None +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=1) + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the SABnzbd sensors.""" from pysabnzbd import SabnzbdApi, SabnzbdApiException - api_key = config.get("api_key") - base_url = config.get("base_url") - name = config.get("name", "SABnzbd") - if not base_url: - _LOGGER.error('Missing config variable base_url') - return False - if not api_key: - _LOGGER.error('Missing config variable api_key') - return False + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + name = config.get(CONF_NAME) + api_key = config.get(CONF_API_KEY) + monitored_types = config.get(CONF_MONITORED_VARIABLES) + base_url = "http://{}:{}/".format(host, port) sab_api = SabnzbdApi(base_url, api_key) try: sab_api.check_available() except SabnzbdApiException: - _LOGGER.exception("Connection to SABnzbd API failed.") + _LOGGER.exception("Connection to SABnzbd API failed") return False # pylint: disable=global-statement global _THROTTLED_REFRESH - _THROTTLED_REFRESH = Throttle(timedelta(seconds=1))(sab_api.refresh_queue) + _THROTTLED_REFRESH = Throttle( + MIN_TIME_BETWEEN_UPDATES)(sab_api.refresh_queue) - dev = [] - for variable in config['monitored_variables']: - if variable['type'] not in SENSOR_TYPES: - _LOGGER.error('Sensor type: "%s" does not exist', variable['type']) - else: - dev.append(SabnzbdSensor(variable['type'], sab_api, name)) + devices = [] + for variable in monitored_types: + devices.append(SabnzbdSensor(variable, sab_api, name)) - add_devices(dev) + add_devices(devices) class SabnzbdSensor(Entity): @@ -79,7 +95,7 @@ class SabnzbdSensor(Entity): @property def name(self): """Return the name of the sensor.""" - return self.client_name + ' ' + self._name + return '{} {}'.format(self.client_name, self._name) @property def state(self): @@ -91,6 +107,7 @@ class SabnzbdSensor(Entity): """Return the unit of measurement of this entity, if any.""" return self._unit_of_measurement + # pylint: disable=no-self-use def refresh_sabnzbd_data(self): """Call the throttled SABnzbd refresh method.""" if _THROTTLED_REFRESH is not None: @@ -98,13 +115,12 @@ class SabnzbdSensor(Entity): try: _THROTTLED_REFRESH() except SabnzbdApiException: - _LOGGER.exception( - self.name + " Connection to SABnzbd API failed." - ) + _LOGGER.exception("Connection to SABnzbd API failed") def update(self): """Get the latest data and updates the states.""" self.refresh_sabnzbd_data() + if self.sabnzb_client.queue: if self.type == 'current_status': self._state = self.sabnzb_client.queue.get('status') From dab5a78f8863f99ce8ae3affa4bc71ed19c453e1 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 16 Aug 2016 21:43:56 +0200 Subject: [PATCH 022/193] Use voluptuous for time/date sensors (#2799) * Use voluptuous for time/date sensors * Extend platform * Remove additional checks --- homeassistant/components/sensor/time_date.py | 28 +++++++++++------- homeassistant/components/sensor/worldclock.py | 29 ++++++++++--------- homeassistant/const.py | 3 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/sensor/time_date.py b/homeassistant/components/sensor/time_date.py index 48760a4463e..ea1b0c1e742 100644 --- a/homeassistant/components/sensor/time_date.py +++ b/homeassistant/components/sensor/time_date.py @@ -5,12 +5,18 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.time_date/ """ import logging - from datetime import timedelta + +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_DISPLAY_OPTIONS import homeassistant.util.dt as dt_util from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv + +TIME_STR_FORMAT = "%H:%M" -_LOGGER = logging.getLogger(__name__) OPTION_TYPES = { 'time': 'Time', 'date': 'Date', @@ -20,7 +26,12 @@ OPTION_TYPES = { 'time_utc': 'Time (UTC)', } -TIME_STR_FORMAT = "%H:%M" +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_DISPLAY_OPTIONS, default=['time']): + vol.All(cv.ensure_list, [vol.In(OPTION_TYPES)]), +}) + +_LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): @@ -29,14 +40,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("Timezone is not set in Home Assistant config") return False - dev = [] - for variable in config['display_options']: - if variable not in OPTION_TYPES: - _LOGGER.error('Option type: "%s" does not exist', variable) - else: - dev.append(TimeDateSensor(variable)) + devices = [] + for variable in config[CONF_DISPLAY_OPTIONS]: + devices.append(TimeDateSensor(variable)) - add_devices(dev) + add_devices(devices) # pylint: disable=too-few-public-methods diff --git a/homeassistant/components/sensor/worldclock.py b/homeassistant/components/sensor/worldclock.py index 0cfc4598cd0..4eed783e510 100644 --- a/homeassistant/components/sensor/worldclock.py +++ b/homeassistant/components/sensor/worldclock.py @@ -6,31 +6,32 @@ https://home-assistant.io/components/sensor.worldclock/ """ import logging +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_NAME, CONF_TIME_ZONE) import homeassistant.util.dt as dt_util from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv -_LOGGER = logging.getLogger(__name__) DEFAULT_NAME = "Worldclock Sensor" ICON = 'mdi:clock' TIME_STR_FORMAT = "%H:%M" +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_TIME_ZONE): cv.time_zone, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Worldclock sensor.""" - try: - time_zone = dt_util.get_time_zone(config.get('time_zone')) - except AttributeError: - _LOGGER.error("time_zone in platform configuration is missing.") - return False + name = config.get(CONF_NAME) + time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE)) - if time_zone is None: - _LOGGER.error("Timezone '%s' is not valid.", config.get('time_zone')) - return False - - add_devices([WorldClockSensor( - time_zone, - config.get('name', DEFAULT_NAME) - )]) + add_devices([WorldClockSensor(time_zone, name)]) class WorldClockSensor(Entity): diff --git a/homeassistant/const.py b/homeassistant/const.py index 61de02041b2..4197cfbf650 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -25,10 +25,11 @@ CONF_ALIAS = 'alias' CONF_API_KEY = 'api_key' CONF_BEFORE = 'before' CONF_BELOW = 'below' -CONF_CONDITION = 'condition' CONF_CODE = 'code' +CONF_CONDITION = 'condition' CONF_CUSTOMIZE = 'customize' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' +CONF_DISPLAY_OPTIONS = 'display_options' CONF_ELEVATION = 'elevation' CONF_ENTITY_ID = 'entity_id' CONF_ENTITY_NAMESPACE = 'entity_namespace' From 822b7f8770fb9277ee62144717bb8b7c50814b0d Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 16 Aug 2016 22:22:55 +0200 Subject: [PATCH 023/193] Use voluptuous for exchange sensors (#2801) * Use voluptuous for exchange sensors * Remove additional checks --- homeassistant/components/sensor/bitcoin.py | 28 +++++++--- .../components/sensor/openexchangerates.py | 56 +++++++++++-------- homeassistant/const.py | 1 + 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/sensor/bitcoin.py b/homeassistant/components/sensor/bitcoin.py index 777571c84c0..0d859314bb4 100644 --- a/homeassistant/components/sensor/bitcoin.py +++ b/homeassistant/components/sensor/bitcoin.py @@ -7,11 +7,16 @@ https://home-assistant.io/components/sensor.bitcoin/ import logging from datetime import timedelta +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_DISPLAY_OPTIONS +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle REQUIREMENTS = ['blockchain==1.3.3'] -_LOGGER = logging.getLogger(__name__) + OPTION_TYPES = { 'exchangerate': ['Exchange rate (1 BTC)', None], 'trade_volume_btc': ['Trade volume', 'BTC'], @@ -35,17 +40,27 @@ OPTION_TYPES = { 'miners_revenue_btc': ['Miners revenue', 'BTC'], 'market_price_usd': ['Market price', 'USD'] } + ICON = 'mdi:currency-btc' +CONF_CURRENCY = 'currency' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DISPLAY_OPTIONS, default=[]): + [vol.In(OPTION_TYPES)], + vol.Optional(CONF_CURRENCY, default='USD'): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) # Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) +MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Bitcoin sensors.""" from blockchain import exchangerates - currency = config.get('currency', 'USD') + currency = config.get(CONF_CURRENCY) if currency not in exchangerates.get_ticker(): _LOGGER.error('Currency "%s" is not available. Using "USD"', currency) @@ -53,11 +68,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): data = BitcoinData() dev = [] - for variable in config['display_options']: - if variable not in OPTION_TYPES: - _LOGGER.error('Option type: "%s" does not exist', variable) - else: - dev.append(BitcoinSensor(data, variable, currency)) + for variable in config[CONF_DISPLAY_OPTIONS]: + dev.append(BitcoinSensor(data, variable, currency)) add_devices(dev) diff --git a/homeassistant/components/sensor/openexchangerates.py b/homeassistant/components/sensor/openexchangerates.py index 920dfc46a90..c7666b8ef80 100644 --- a/homeassistant/components/sensor/openexchangerates.py +++ b/homeassistant/components/sensor/openexchangerates.py @@ -6,47 +6,57 @@ https://home-assistant.io/components/sensor.openexchangerates/ """ from datetime import timedelta import logging + import requests +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_API_KEY, CONF_NAME, CONF_PAYLOAD) +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -from homeassistant.const import CONF_API_KEY _RESOURCE = 'https://openexchangerates.org/api/latest.json' _LOGGER = logging.getLogger(__name__) -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=100) + CONF_BASE = 'base' CONF_QUOTE = 'quote' -CONF_NAME = 'name' + DEFAULT_NAME = 'Exchange Rate Sensor' +DEFAULT_BASE = 'USD' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_QUOTE): cv.string, + vol.Optional(CONF_BASE, default=DEFAULT_BASE): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_UPDATES = timedelta(hours=2) def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Openexchangerates sensor.""" - payload = config.get('payload', None) - rest = OpenexchangeratesData( - _RESOURCE, - config.get(CONF_API_KEY), - config.get(CONF_BASE, 'USD'), - config.get(CONF_QUOTE), - payload - ) - response = requests.get(_RESOURCE, params={'base': config.get(CONF_BASE, - 'USD'), - 'app_id': - config.get(CONF_API_KEY)}, + """Setup the Open Exchange Rates sensor.""" + name = config.get(CONF_NAME) + api_key = config.get(CONF_API_KEY) + base = config.get(CONF_BASE) + quote = config.get(CONF_QUOTE) + payload = config.get(CONF_PAYLOAD) + + rest = OpenexchangeratesData(_RESOURCE, api_key, base, quote, payload) + response = requests.get(_RESOURCE, params={'base': base, + 'app_id': api_key}, timeout=10) if response.status_code != 200: - _LOGGER.error("Check your OpenExchangeRates API") + _LOGGER.error("Check your OpenExchangeRates API key") return False rest.update() - add_devices([OpenexchangeratesSensor(rest, config.get(CONF_NAME, - DEFAULT_NAME), - config.get(CONF_QUOTE))]) + add_devices([OpenexchangeratesSensor(rest, name, quote)]) class OpenexchangeratesSensor(Entity): - """Representation of an Openexchangerates sensor.""" + """Representation of an Open Exchange Rates sensor.""" def __init__(self, rest, name, quote): """Initialize the sensor.""" @@ -100,6 +110,6 @@ class OpenexchangeratesData(object): timeout=10) self.data = result.json()['rates'] except requests.exceptions.HTTPError: - _LOGGER.error("Check Openexchangerates API Key") + _LOGGER.error("Check the Openexchangerates API Key") self.data = None return False diff --git a/homeassistant/const.py b/homeassistant/const.py index 4197cfbf650..52d71d141ac 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -46,6 +46,7 @@ CONF_NAME = 'name' CONF_OFFSET = 'offset' CONF_OPTIMISTIC = 'optimistic' CONF_PASSWORD = 'password' +CONF_PAYLOAD = 'payload' CONF_PENDING_TIME = 'pending_time' CONF_PLATFORM = 'platform' CONF_PORT = 'port' From 72fc526ee8838de35dbf7acbb3e0875a0b34b022 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Tue, 16 Aug 2016 14:26:01 -0700 Subject: [PATCH 024/193] Html5 notifications improvements (#2840) * Retry sending the push for 1 day instead of failing instantly if the target is unavailable * Add timestamp to push payload * Correctly use the title and body fields for their intended purposes * Add callback support * Revert changes to frontend files. * Add default URL which will open Home Assistant. Also put all the data into the data object of the payload so it is accessible in the browser. Without doing this, things like URL wouldnt be accessible. * Flake8 and pylint fixes * event->type * Dont send the default url if actions exist * flake8/pylint fixes again * Update html5 tests * Remove callbacks from this branch, will re-stage on a different branch * Remove remnant of callbacks * Add url to data dictionary if it exists instead of copying the entire data dictionary in * flake8 fix --- homeassistant/components/notify/html5.py | 18 +++++++++++++++--- tests/components/notify/test_html5.py | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 70ab9580a04..04e49ecabca 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -7,6 +7,7 @@ https://home-assistant.io/components/notify.html5/ import os import logging import json +import time import voluptuous as vol from voluptuous.humanize import humanize_error @@ -15,7 +16,7 @@ from homeassistant.const import ( HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR) from homeassistant.util import ensure_unique_string from homeassistant.components.notify import ( - ATTR_TARGET, ATTR_DATA, BaseNotificationService, + ATTR_TARGET, ATTR_TITLE, ATTR_DATA, BaseNotificationService, PLATFORM_SCHEMA) from homeassistant.components.http import HomeAssistantView from homeassistant.components.frontend import add_manifest_json_key @@ -145,9 +146,14 @@ class HTML5NotificationService(BaseNotificationService): """Send a message to a user.""" from pywebpush import WebPusher + timestamp = int(time.time()) + payload = { - 'title': message, + 'body': message, + 'data': {}, 'icon': '/static/icons/favicon-192x192.png', + 'timestamp': (timestamp*1000), # Javascript ms since epoch + 'title': kwargs.get(ATTR_TITLE) } data = kwargs.get(ATTR_DATA) @@ -155,6 +161,12 @@ class HTML5NotificationService(BaseNotificationService): if data: payload.update(data) + if data.get('url') is not None: + payload['data']['url'] = data.get('url') + elif (payload['data'].get('url') is None and + payload.get('actions') is None): + payload['data']['url'] = '/' + targets = kwargs.get(ATTR_TARGET) if not targets: @@ -170,4 +182,4 @@ class HTML5NotificationService(BaseNotificationService): continue WebPusher(info[ATTR_SUBSCRIPTION]).send( - json.dumps(payload), gcm_key=self._gcm_key, ttl='0') + json.dumps(payload), gcm_key=self._gcm_key, ttl='86400') diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py index b562775d32e..121cc1096d2 100644 --- a/tests/components/notify/test_html5.py +++ b/tests/components/notify/test_html5.py @@ -65,7 +65,7 @@ class TestHtml5Notify(object): # Call to send payload = json.loads(mock_wp.mock_calls[1][1][0]) - assert payload['title'] == 'Hello' + assert payload['body'] == 'Hello' assert payload['icon'] == 'beer.png' def test_registering_new_device_view(self): From f668a884853ef40560d6d13b18e68a280cda5bf9 Mon Sep 17 00:00:00 2001 From: Maggi Trymbill Date: Tue, 16 Aug 2016 18:24:37 -0700 Subject: [PATCH 025/193] Fixed typo (#2856) Pretty sure this is a typo ... it made finding the plist and logs a bit of a headache for me at least :) --- homeassistant/scripts/macos/launchd.plist | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/scripts/macos/launchd.plist b/homeassistant/scripts/macos/launchd.plist index 50bc18e3e38..b65cdac7439 100644 --- a/homeassistant/scripts/macos/launchd.plist +++ b/homeassistant/scripts/macos/launchd.plist @@ -3,7 +3,7 @@ Label - org.homeassitant + org.homeassistant EnvironmentVariables @@ -27,10 +27,10 @@ StandardErrorPath - /Users/$USER$/Library/Logs/homeassitant.log + /Users/$USER$/Library/Logs/homeassistant.log StandardOutPath - /Users/$USER$/Library/Logs/homeassitant.log + /Users/$USER$/Library/Logs/homeassistant.log From 324ddfdaeb14e26a4e42ae22e6877410ab88a77e Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Tue, 16 Aug 2016 23:53:00 -0400 Subject: [PATCH 026/193] fix flux_update service (#2792) * fix flux_update service * fix tests * give update service unique name * remove unnecessary param * Revert "fix tests" This reverts commit 2fd7760455f5389b0de2e3ce272090c551d87201. * fix flux_update --- homeassistant/components/switch/flux.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/flux.py b/homeassistant/components/switch/flux.py index a66b45bc82e..61a40315620 100644 --- a/homeassistant/components/switch/flux.py +++ b/homeassistant/components/switch/flux.py @@ -101,7 +101,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Update lights.""" flux.flux_update() - hass.services.register(DOMAIN, 'flux_update', update) + hass.services.register(DOMAIN, name + '_update', update) # pylint: disable=too-many-instance-attributes @@ -151,8 +151,10 @@ class FluxSwitch(SwitchDevice): self.update_ha_state() # pylint: disable=too-many-locals - def flux_update(self, now=dt_now()): + def flux_update(self, now=None): """Update all the lights using flux.""" + if now is None: + now = dt_now() sunset = next_setting(self.hass, SUN).replace(day=now.day, month=now.month, year=now.year) From 781fe9c54e7ce53a11e89267a439a99705101827 Mon Sep 17 00:00:00 2001 From: Kevin Gottsman Date: Tue, 16 Aug 2016 23:53:59 -0400 Subject: [PATCH 027/193] Fix logging message for disarm (#2857) --- homeassistant/components/alarm_control_panel/alarmdotcom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/alarm_control_panel/alarmdotcom.py b/homeassistant/components/alarm_control_panel/alarmdotcom.py index 385cabb7d02..542cb5e3d02 100644 --- a/homeassistant/components/alarm_control_panel/alarmdotcom.py +++ b/homeassistant/components/alarm_control_panel/alarmdotcom.py @@ -80,7 +80,7 @@ class AlarmDotCom(alarm.AlarmControlPanel): def alarm_disarm(self, code=None): """Send disarm command.""" - if not self._validate_code(code, 'arming home'): + if not self._validate_code(code, 'disarming home'): return from pyalarmdotcom.pyalarmdotcom import Alarmdotcom # Open another session to alarm.com to fire off the command From 4fcfffc17203c85030d1214f23523d3b53137f47 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 17 Aug 2016 05:55:29 +0200 Subject: [PATCH 028/193] add tcp/udp port to config validation (#2854) --- homeassistant/components/envisalink.py | 3 +-- homeassistant/components/homematic.py | 23 ++++++++++------------ homeassistant/components/sensor/imap.py | 3 +-- homeassistant/components/sensor/plex.py | 4 +--- homeassistant/helpers/config_validation.py | 1 + tests/helpers/test_config_validation.py | 12 +++++++++++ 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/envisalink.py b/homeassistant/components/envisalink.py index ab4312ff20f..eea06307f7d 100644 --- a/homeassistant/components/envisalink.py +++ b/homeassistant/components/envisalink.py @@ -62,8 +62,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_CODE): cv.string, vol.Optional(CONF_ZONES): {vol.Coerce(int): ZONE_SCHEMA}, vol.Optional(CONF_PARTITIONS): {vol.Coerce(int): PARTITION_SCHEMA}, - vol.Optional(CONF_EVL_PORT, default=DEFAULT_PORT): - vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + vol.Optional(CONF_EVL_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_EVL_VERSION, default=DEFAULT_EVL_VERSION): vol.All(vol.Coerce(int), vol.Range(min=3, max=4)), vol.Optional(CONF_EVL_KEEPALIVE, default=DEFAULT_KEEPALIVE): diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index fb3316c9bd6..1a917789638 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -10,6 +10,7 @@ import logging from functools import partial import voluptuous as vol +import homeassistant.helpers.config_validation as cv from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN, CONF_USERNAME, CONF_PASSWORD) from homeassistant.helpers.entity import Entity @@ -97,25 +98,21 @@ CONF_RESOLVENAMES = 'resolvenames' CONF_DELAY = 'delay' PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_LOCAL_IP): vol.Coerce(str), - vol.Optional(CONF_LOCAL_PORT, default=8943): - vol.All(vol.Coerce(int), - vol.Range(min=1, max=65535)), - vol.Required(CONF_REMOTE_IP): vol.Coerce(str), - vol.Optional(CONF_REMOTE_PORT, default=2001): - vol.All(vol.Coerce(int), - vol.Range(min=1, max=65535)), + vol.Required(CONF_LOCAL_IP): cv.string, + vol.Optional(CONF_LOCAL_PORT, default=8943): cv.port, + vol.Required(CONF_REMOTE_IP): cv.string, + vol.Optional(CONF_REMOTE_PORT, default=2001): cv.port, vol.Optional(CONF_RESOLVENAMES, default=False): vol.In(CONF_RESOLVENAMES_OPTIONS), - vol.Optional(CONF_USERNAME, default="Admin"): vol.Coerce(str), - vol.Optional(CONF_PASSWORD, default=""): vol.Coerce(str), - vol.Optional(CONF_DELAY, default=0.5): vol.Coerce(float) + vol.Optional(CONF_USERNAME, default="Admin"): cv.string, + vol.Optional(CONF_PASSWORD, default=""): cv.string, + vol.Optional(CONF_DELAY, default=0.5): cv.string, }) SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({ - vol.Required(ATTR_ADDRESS): vol.Coerce(str), + vol.Required(ATTR_ADDRESS): cv.string, vol.Required(ATTR_CHANNEL): vol.Coerce(int), - vol.Required(ATTR_PARAM): vol.Coerce(str) + vol.Required(ATTR_PARAM): cv.string, }) diff --git a/homeassistant/components/sensor/imap.py b/homeassistant/components/sensor/imap.py index c458799215f..9958ff5a36a 100644 --- a/homeassistant/components/sensor/imap.py +++ b/homeassistant/components/sensor/imap.py @@ -28,8 +28,7 @@ PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_USER): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_SERVER): cv.string, - vol.Optional(CONF_PORT, default=DEFAULT_PORT): - vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) diff --git a/homeassistant/components/sensor/plex.py b/homeassistant/components/sensor/plex.py index 89ffd020bdd..4ef01304488 100644 --- a/homeassistant/components/sensor/plex.py +++ b/homeassistant/components/sensor/plex.py @@ -28,9 +28,7 @@ PLATFORM_SCHEMA = vol.Schema({ vol.Optional(CONF_SERVER): cv.string, vol.Optional(CONF_NAME, default='Plex'): cv.string, vol.Optional(CONF_HOST, default='localhost'): cv.string, - vol.Optional(CONF_PORT, default=32400): vol.All(vol.Coerce(int), - vol.Range(min=1, - max=65535)) + vol.Optional(CONF_PORT, default=32400): cv.port, }) diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index 91a05b37b5d..ff1f694151f 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -29,6 +29,7 @@ latitude = vol.All(vol.Coerce(float), vol.Range(min=-90, max=90), longitude = vol.All(vol.Coerce(float), vol.Range(min=-180, max=180), msg='invalid longitude') sun_event = vol.All(vol.Lower, vol.Any(SUN_EVENT_SUNSET, SUN_EVENT_SUNRISE)) +port = vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)) # typing typevar T = TypeVar('T') diff --git a/tests/helpers/test_config_validation.py b/tests/helpers/test_config_validation.py index 7f94ab53b23..3a72ef1da37 100644 --- a/tests/helpers/test_config_validation.py +++ b/tests/helpers/test_config_validation.py @@ -47,6 +47,18 @@ def test_longitude(): schema(value) +def test_port(): + """Test tcp/udp network port.""" + schema = vol.Schema(cv.port) + + for value in('invalid', None, -1, 0, 80000, '81000'): + with pytest.raises(vol.MultipleInvalid): + schema(value) + + for value in ('1000', 21, 24574): + schema(value) + + def test_platform_config(): """Test platform config validation.""" for value in ( From 37561765ff94ffe024739c911074aa21efd4fb5d Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Tue, 16 Aug 2016 21:08:57 -0700 Subject: [PATCH 029/193] Add Gravatar support to device_tracker (#2836) * Support passing an email address linked to Gravatar as the picture in known_devices. * Add a dedicated field for Gravatar * Bring tests back up to where they were before Gravatar. * Add tests for Gravatar. --- .../components/device_tracker/__init__.py | 16 +++++++++++-- tests/components/device_tracker/test_init.py | 24 ++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index d518587d298..8c52f2147b3 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -258,7 +258,7 @@ class Device(Entity): _state = STATE_NOT_HOME def __init__(self, hass, consider_home, home_range, track, dev_id, mac, - name=None, picture=None, away_hide=False): + name=None, picture=None, gravatar=None, away_hide=False): """Initialize a device.""" self.hass = hass self.entity_id = ENTITY_ID_FORMAT.format(dev_id) @@ -280,7 +280,11 @@ class Device(Entity): self.config_name = name # Configured picture - self.config_picture = picture + if gravatar is not None: + self.config_picture = get_gravatar_for_email(gravatar) + else: + self.config_picture = picture + self.away_hide = away_hide @property @@ -382,6 +386,7 @@ def load_config(path, hass, consider_home, home_range): Device(hass, consider_home, home_range, device.get('track', False), str(dev_id).lower(), 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()] except HomeAssistantError: @@ -425,3 +430,10 @@ def update_config(path, dev_id, device): (CONF_AWAY_HIDE, 'yes' if device.away_hide else 'no')): out.write(' {}: {}\n'.format(key, '' if value is None else value)) + + +def get_gravatar_for_email(email): + """Return an 80px Gravatar for the given email address.""" + import hashlib + url = "https://www.gravatar.com/avatar/{}.jpg?s=80&d=wavatar" + return url.format(hashlib.md5(email.encode('utf-8').lower()).hexdigest()) diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index a88b4d18de4..c6721b8c8cc 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -63,7 +63,8 @@ class TestComponentsDeviceTracker(unittest.TestCase): dev_id = 'test' device = device_tracker.Device( self.hass, timedelta(seconds=180), 0, True, dev_id, - 'AB:CD:EF:GH:IJ', 'Test name', 'http://test.picture', True) + 'AB:CD:EF:GH:IJ', 'Test name', picture='http://test.picture', + away_hide=True) device_tracker.update_config(self.yaml_devices, dev_id, device) self.assertTrue(device_tracker.setup(self.hass, {})) config = device_tracker.load_config(self.yaml_devices, self.hass, @@ -94,6 +95,27 @@ class TestComponentsDeviceTracker(unittest.TestCase): assert config[0].dev_id == 'dev1' assert config[0].track + def test_gravatar(self): + """Test the Gravatar generation.""" + dev_id = 'test' + device = device_tracker.Device( + self.hass, timedelta(seconds=180), 0, True, dev_id, + 'AB:CD:EF:GH:IJ', 'Test name', gravatar='test@example.com') + gravatar_url = ("https://www.gravatar.com/avatar/" + "55502f40dc8b7c769880b10874abc9d0.jpg?s=80&d=wavatar") + self.assertEqual(device.config_picture, gravatar_url) + + def test_gravatar_and_picture(self): + """Test that Gravatar overrides picture.""" + dev_id = 'test' + device = device_tracker.Device( + self.hass, timedelta(seconds=180), 0, True, dev_id, + 'AB:CD:EF:GH:IJ', 'Test name', picture='http://test.picture', + gravatar='test@example.com') + gravatar_url = ("https://www.gravatar.com/avatar/" + "55502f40dc8b7c769880b10874abc9d0.jpg?s=80&d=wavatar") + self.assertEqual(device.config_picture, gravatar_url) + def test_discovery(self): """Test discovery.""" scanner = get_component('device_tracker.test').SCANNER From c1ce6855c5aa2b71c27aff913032d78c0d4b6761 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Tue, 16 Aug 2016 22:05:41 -0700 Subject: [PATCH 030/193] Expose notify platform targets as individual services (#2837) * First pass on providing individual services for all possible targets that a notification platform supports. * Add a quite hacky first version of notification groups * Add a docstring for get_targets * Register group service under notifygroup/ and safely check for notifygroups in config * Remove notifygroups, because it belongs in its own PR * Make @balloob requested changes * get_targets()->targets * Add tests for notify targets exposed as individual services * If we dont have a platform name set in configuration, lets use the name of the platform instead of notify * Fix test docstring. * Dont use a dictionary for just one value * No need to double slugify * targets is now just a list of strings instead of a dict --- homeassistant/components/notify/__init__.py | 26 +++++++++++++++-- homeassistant/components/notify/demo.py | 5 ++++ homeassistant/components/notify/html5.py | 5 ++++ tests/components/notify/test_demo.py | 31 +++++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/notify/__init__.py b/homeassistant/components/notify/__init__.py index 782a4510ffb..a28a50d766f 100644 --- a/homeassistant/components/notify/__init__.py +++ b/homeassistant/components/notify/__init__.py @@ -64,6 +64,7 @@ def send_message(hass, message, title=None, data=None): hass.services.call(DOMAIN, SERVICE_NOTIFY, info) +# pylint: disable=too-many-locals def setup(hass, config): """Setup the notify services.""" success = False @@ -71,6 +72,8 @@ def setup(hass, config): descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) + targets = {} + for platform, p_config in config_per_platform(config, DOMAIN): notify_implementation = bootstrap.prepare_setup_platform( hass, config, DOMAIN, platform) @@ -92,7 +95,10 @@ def setup(hass, config): title = template.render( hass, call.data.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)) - target = call.data.get(ATTR_TARGET) + if targets.get(call.service) is not None: + target = targets[call.service] + else: + target = call.data.get(ATTR_TARGET) message = template.render(hass, message) data = call.data.get(ATTR_DATA) @@ -100,8 +106,22 @@ def setup(hass, config): data=data) service_call_handler = partial(notify_message, notify_service) - service_name = slugify(p_config.get(CONF_NAME) or SERVICE_NOTIFY) - hass.services.register(DOMAIN, service_name, service_call_handler, + + if hasattr(notify_service, 'targets'): + platform_name = (p_config.get(CONF_NAME) or platform) + for target in notify_service.targets: + target_name = slugify("{}_{}".format(platform_name, target)) + targets[target_name] = target + hass.services.register(DOMAIN, target_name, + service_call_handler, + descriptions.get(SERVICE_NOTIFY), + schema=NOTIFY_SERVICE_SCHEMA) + + platform_name = (p_config.get(CONF_NAME) or SERVICE_NOTIFY) + platform_name_slug = slugify(platform_name) + + hass.services.register(DOMAIN, platform_name_slug, + service_call_handler, descriptions.get(SERVICE_NOTIFY), schema=NOTIFY_SERVICE_SCHEMA) success = True diff --git a/homeassistant/components/notify/demo.py b/homeassistant/components/notify/demo.py index 4685b90e880..8ad74b1ac8e 100644 --- a/homeassistant/components/notify/demo.py +++ b/homeassistant/components/notify/demo.py @@ -22,6 +22,11 @@ class DemoNotificationService(BaseNotificationService): """Initialize the service.""" self.hass = hass + @property + def targets(self): + """Return a dictionary of registered targets.""" + return ["test target"] + def send_message(self, message="", **kwargs): """Send a message to a user.""" kwargs['message'] = message diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 04e49ecabca..7d9b89471b4 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -142,6 +142,11 @@ class HTML5NotificationService(BaseNotificationService): self._gcm_key = gcm_key self.registrations = registrations + @property + def targets(self): + """Return a dictionary of registered targets.""" + return self.registrations.keys() + def send_message(self, message="", **kwargs): """Send a message to a user.""" from pywebpush import WebPusher diff --git a/tests/components/notify/test_demo.py b/tests/components/notify/test_demo.py index 3f7ffb576ed..f0a05a01c1f 100644 --- a/tests/components/notify/test_demo.py +++ b/tests/components/notify/test_demo.py @@ -22,6 +22,7 @@ class TestNotifyDemo(unittest.TestCase): } })) self.events = [] + self.calls = [] def record_event(event): """Record event to send notification.""" @@ -33,6 +34,10 @@ class TestNotifyDemo(unittest.TestCase): """"Stop down everything that was started.""" self.hass.stop() + def record_calls(self, *args): + """Helper for recording calls.""" + self.calls.append(args) + def test_sending_none_message(self): """Test send with None as message.""" notify.send_message(self.hass, None) @@ -93,3 +98,29 @@ data_template: 'sound': 'US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav'}} } == self.events[0].data + + def test_targets_are_services(self): + """Test that all targets are exposed as individual services.""" + self.assertIsNotNone(self.hass.services.has_service("notify", "demo")) + service = "demo_test_target" + self.assertIsNotNone(self.hass.services.has_service("notify", service)) + + def test_messages_to_targets_route(self): + """Test message routing to specific target services.""" + self.hass.bus.listen_once("notify", self.record_calls) + + self.hass.services.call("notify", "demo_test_target", + {'message': 'my message', + 'title': 'my title', + 'data': {'hello': 'world'}}) + + self.hass.pool.block_till_done() + + data = self.calls[0][0].data + + assert { + 'message': 'my message', + 'target': 'test target', + 'title': 'my title', + 'data': {'hello': 'world'} + } == data From 848781fbb757449f8159ec14b1aa3055560d5e06 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Tue, 16 Aug 2016 22:14:04 -0700 Subject: [PATCH 031/193] Add a group notify platform (#2842) * Add a group notify platform which allows sending a single notification to multiple platforms. * Correctly sort group.py * Clean up the payload logic * Make name and entity id required in the schema * Deep update the dictionary to fix a bug where data wasnt merging. * Add notify.group tests. * Improve docstrings. * Change entities to services and entity_id to service * Make service a slug without a default value * Update tests for entities->services, entity_id->service * vol.Any(cv.slug) -> cv.slug --- .coveragerc | 1 + homeassistant/components/notify/group.py | 65 +++++++++++++++++++ tests/components/notify/test_group.py | 82 ++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 homeassistant/components/notify/group.py create mode 100644 tests/components/notify/test_group.py diff --git a/.coveragerc b/.coveragerc index 9c8a4695537..acb72210603 100644 --- a/.coveragerc +++ b/.coveragerc @@ -173,6 +173,7 @@ omit = homeassistant/components/notify/aws_sqs.py homeassistant/components/notify/free_mobile.py homeassistant/components/notify/gntp.py + homeassistant/components/notify/group.py homeassistant/components/notify/instapush.py homeassistant/components/notify/joaoapps_join.py homeassistant/components/notify/message_bird.py diff --git a/homeassistant/components/notify/group.py b/homeassistant/components/notify/group.py new file mode 100644 index 00000000000..522b231d8cf --- /dev/null +++ b/homeassistant/components/notify/group.py @@ -0,0 +1,65 @@ +""" +Group platform for notify component. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.group/ +""" +import collections +import logging +import voluptuous as vol + +from homeassistant.const import (CONF_PLATFORM, CONF_NAME, ATTR_SERVICE) +from homeassistant.components.notify import (DOMAIN, ATTR_MESSAGE, ATTR_DATA, + BaseNotificationService) +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +CONF_SERVICES = "services" + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "group", + vol.Required(CONF_NAME): vol.Coerce(str), + vol.Required(CONF_SERVICES): vol.All(cv.ensure_list, [{ + vol.Required(ATTR_SERVICE): cv.slug, + vol.Optional(ATTR_DATA): dict, + }]) +}) + + +def update(input_dict, update_source): + """Deep update a dictionary.""" + for key, val in update_source.items(): + if isinstance(val, collections.Mapping): + recurse = update(input_dict.get(key, {}), val) + input_dict[key] = recurse + else: + input_dict[key] = update_source[key] + return input_dict + + +def get_service(hass, config): + """Get the Group notification service.""" + return GroupNotifyPlatform(hass, config.get(CONF_SERVICES)) + + +# pylint: disable=too-few-public-methods +class GroupNotifyPlatform(BaseNotificationService): + """Implement the notification service for the group notify playform.""" + + def __init__(self, hass, entities): + """Initialize the service.""" + self.hass = hass + self.entities = entities + + def send_message(self, message="", **kwargs): + """Send message to all entities in the group.""" + payload = {ATTR_MESSAGE: message} + payload.update({key: val for key, val in kwargs.items() if val}) + + for entity in self.entities: + sending_payload = payload.copy() + if entity.get(ATTR_DATA) is not None: + update(sending_payload, entity.get(ATTR_DATA)) + self.hass.services.call(DOMAIN, entity.get(ATTR_SERVICE), + sending_payload) diff --git a/tests/components/notify/test_group.py b/tests/components/notify/test_group.py new file mode 100644 index 00000000000..20e2259ca6e --- /dev/null +++ b/tests/components/notify/test_group.py @@ -0,0 +1,82 @@ +"""The tests for the notify.group platform.""" +import unittest + +import homeassistant.components.notify as notify +from homeassistant.components.notify import group + +from tests.common import get_test_home_assistant + + +class TestNotifyGroup(unittest.TestCase): + """Test the notify.group platform.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.events = [] + self.assertTrue(notify.setup(self.hass, { + 'notify': { + 'name': 'demo1', + 'platform': 'demo' + } + })) + self.assertTrue(notify.setup(self.hass, { + 'notify': { + 'name': 'demo2', + 'platform': 'demo' + } + })) + + self.service = group.get_service(self.hass, {'services': [ + {'service': 'demo1'}, + {'service': 'demo2', + 'data': {'target': 'unnamed device', + 'data': {'test': 'message'}}}]}) + + assert self.service is not None + + def record_event(event): + """Record event to send notification.""" + self.events.append(event) + + self.hass.bus.listen("notify", record_event) + + def tearDown(self): # pylint: disable=invalid-name + """"Stop everything that was started.""" + self.hass.stop() + + def test_send_message_to_group(self): + """Test sending a message to a notify group.""" + self.service.send_message('Hello', title='Test notification') + self.hass.pool.block_till_done() + self.assertTrue(len(self.events) == 2) + last_event = self.events[-1] + self.assertEqual(last_event.data[notify.ATTR_TITLE], + 'Test notification') + self.assertEqual(last_event.data[notify.ATTR_MESSAGE], 'Hello') + + def test_send_message_with_data(self): + """Test sending a message with to a notify group.""" + notify_data = {'hello': 'world'} + self.service.send_message('Hello', title='Test notification', + data=notify_data) + self.hass.pool.block_till_done() + last_event = self.events[-1] + self.assertEqual(last_event.data[notify.ATTR_TITLE], + 'Test notification') + self.assertEqual(last_event.data[notify.ATTR_MESSAGE], 'Hello') + self.assertEqual(last_event.data[notify.ATTR_DATA], notify_data) + + def test_entity_data_passes_through(self): + """Test sending a message with data to merge to a notify group.""" + notify_data = {'hello': 'world'} + self.service.send_message('Hello', title='Test notification', + data=notify_data) + self.hass.pool.block_till_done() + data = self.events[-1].data + assert { + 'message': 'Hello', + 'target': 'unnamed device', + 'title': 'Test notification', + 'data': {'hello': 'world', 'test': 'message'} + } == data From 4a847dbd915ec8fb4049f0e70df9fb9bb2d25372 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 17 Aug 2016 07:40:20 +0200 Subject: [PATCH 032/193] new yahooweather version and fix update function (#2848) --- homeassistant/components/sensor/yweather.py | 5 ++++- requirements_all.txt | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/yweather.py b/homeassistant/components/sensor/yweather.py index c308d36f50b..b0156497177 100644 --- a/homeassistant/components/sensor/yweather.py +++ b/homeassistant/components/sensor/yweather.py @@ -13,7 +13,7 @@ from homeassistant.const import (CONF_PLATFORM, TEMP_CELSIUS, from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -REQUIREMENTS = ["yahooweather==0.6"] +REQUIREMENTS = ["yahooweather==0.7"] SENSOR_TYPES = { 'weather_current': ['Current', None], @@ -139,6 +139,9 @@ class YahooWeatherSensor(Entity): def update(self): """Get the latest data from Yahoo! and updates the states.""" self._data.update() + if not self._data.yahoo.RawData: + _LOGGER.info("Don't receive weather data from yahoo!") + return # default code for weather image self._code = self._data.yahoo.Now["code"] diff --git a/requirements_all.txt b/requirements_all.txt index 26a4afdeb63..4f0a4aa12e6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -473,7 +473,7 @@ xbee-helper==0.0.7 xmltodict==0.10.2 # homeassistant.components.sensor.yweather -yahooweather==0.6 +yahooweather==0.7 # homeassistant.components.zeroconf zeroconf==0.17.6 From 7720a17c18505c7f3091d4fe999e7d964e91f231 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 16 Aug 2016 23:02:19 -0700 Subject: [PATCH 033/193] Add badge --- .../frontend/www_static/home-assistant-polymer | 2 +- .../frontend/www_static/images/badge.png | Bin 0 -> 2962 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 homeassistant/components/frontend/www_static/images/badge.png diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index af4af1e9332..dd6ee9544e7 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit af4af1e9332afef90d25d61589840d239baf7ded +Subproject commit dd6ee9544e7129b1735fe2377311ff2e2b7449c0 diff --git a/homeassistant/components/frontend/www_static/images/badge.png b/homeassistant/components/frontend/www_static/images/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..2d254444915e9d6eef36576817adfcd79a72fb57 GIT binary patch literal 2962 zcmaJ@dpK128$WY#PpXNOT4P$uWtcN}gBZrGG9<|*F=h@X%#4{~#-*C1-+hiMgxGYy?ZjdEJUiTOiU+|% zX$%sPK_FniJ~-H$ zm>0(IX1RRz1<&ko5mKp$VPz$g$t-0gOQAU23beMiUgRJW@vsG65-*T)6xVp~6_H9S&Cd&o6T*Sg??B^IW`2XOaK%^5ukVYoZhy*Gf z1RbrNm@ERBN+uBK))X=e_Z7?gTim|nC%gjd7cI$P@Iq-Y2Ze`+DIq+}NypPUbPyj# zr9c#rKn|rrB%Bp2&uTGc{+2>ZOK@H;4*x0$c=A_CK?1mr#Bjmf?7PAO0JU@OET)hA z;qO6-XLX(ROB%nq)?vu6Wcs?47O3VgR2G&g2QTIBb^EZw``x}X$~I-&J|o|)JFhGm~Dirh2lI>fknS-f?AZF)*23(xPJ0g08>QP3y3k zUI!>$WUhNrM$aC+z8&c>W-zqMwzu0}r&a%wvA&VxAaObpFwjT@ssUX^9ij!{a`CZV zYz=Pski5-6F5g^&Gh6s2TDvsR;Q$`^9;nuxKJ~qcT64DjF7VB11&Vqs1f}G3PioT3 z-r9YKz#B(|WdLSl!nD~7U`J6JOJDne8Xb3CsHjx9m}q&`xVZ&0w|F2%fk=%kRFUX8 z1lZuxy%6+@?2Z#P$g{bf8R`~yt96I9*z+EW=HgjQQmpyvGRknP<3og5yIi$@#=e># zdU1r46wIFeufn)^s?TUp^GF6|dtiOGudx7!ObOyGY*z2wmOFmHVeU-BMg_)bO(Y5N zsWx}tFOC*HAAa;_`>76W&#j_ph%RBz>A?lNRuAbEYIWLc(`03XL~Zyb6%r+9a7m5Kdj%gq;VtX@C=6iL>|i6cZ}1*S12JZ+V8YEmCJ zl4`^8wwgk7Oz(RG`OL`b86YG45q21maLvw zkYnf*__7ch_h)r1Ka|@biO~!pDytq0w4w=zk_;}q@AojbJ0nzUp?KSKfIxZdGTEJ zL|~vwUZYM(onha2-b>w;N9Nacol1YYY9e%+t%;mRPn3DxwFq%$t*lK(pUs?2zGxKW zJ8*Jx6sBv zX)tX*(BzaRFq!b~SS2#u^wdysVwJuqrabEK@DN5(&u`Sx`4ldCJ{1Wg+U>i*;H>j2$fFCnWQ+>x zNk16J3_n|E&Xz?gCfctjTweaXL5opZ=5IKb63d-_WOjqjSpyvWxmEY=RqQ7lYVC~N`(lRsiH%j~D)@R5Lt=W!c zmBIOyyFzL@>Fh>^|uFtDjKo%p4OaJv)B6NK;OjZ{<~eap1A_jrgNvTuLBBZ zcBH?sEv><}ui3QhRArUM^U-Cay6oA@tFBA+$Df?WbZAc%Vf(~g%h_^I=6pI`hsPQ; z5FII{+V+U|Ms4Dkyx3JBSvx`*`41w|X@|_|(ZJPs>Y>{o^LyG-%?4I8w_J-|QQZsH z8TXaN%Y?fTd#k~!qiG9_wfCE5asw(xZ5_tADQ`|~S2OG5|KTgGAKr33z-36fJjHMJ zb#752QIXV?1?X(sm+-6JR7FKycc6CuF4h*`ilH{Qd!|5hGDXq5alEmp4fW*cm}~61 zyIyM&D$|gqWsSdwD*|!jGsJtZeCf_8rCf>HaKv@;TZ`jY=;>3&`={O~)6Y+Mxr9v= z&J|Z(03%B3V!G&Q6~gc<=3W8#3+7urCU0CcXX=bUX+r*lXwdQqw7IAFBlFvm8uGJm z3=Yk|K*Xr#3_Rj95(?QjEvpM`{fI9z1?h<+qx%=A68K!F~%& zeN9i4#$|NQ$j5=hiu1Ro4b@95+RQYOb9;ehhD4nM6?tFDvl`*8kD9eTHhTwC}+Sywnup=Jwz03uqQ z?d(b)`A2FgshSFtnfr$QKQ5d*gmJje`^_OTdah7B7ns}eT7EF9+ Date: Tue, 16 Aug 2016 23:05:00 -0700 Subject: [PATCH 034/193] Add default badge to push notification (#2859) --- .../images/{badge.png => notification-badge.png} | Bin homeassistant/components/notify/html5.py | 1 + 2 files changed, 1 insertion(+) rename homeassistant/components/frontend/www_static/images/{badge.png => notification-badge.png} (100%) diff --git a/homeassistant/components/frontend/www_static/images/badge.png b/homeassistant/components/frontend/www_static/images/notification-badge.png similarity index 100% rename from homeassistant/components/frontend/www_static/images/badge.png rename to homeassistant/components/frontend/www_static/images/notification-badge.png diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 7d9b89471b4..33ebe8e0c0d 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -157,6 +157,7 @@ class HTML5NotificationService(BaseNotificationService): 'body': message, 'data': {}, 'icon': '/static/icons/favicon-192x192.png', + 'badge': '/static/images/notification-badge.png', 'timestamp': (timestamp*1000), # Javascript ms since epoch 'title': kwargs.get(ATTR_TITLE) } From 8a3c511a04589a9f6f98562198abbdc57f23f353 Mon Sep 17 00:00:00 2001 From: Matthias Grawinkel Date: Wed, 17 Aug 2016 19:08:47 +0200 Subject: [PATCH 035/193] Adding Digest Auth for webcam image retrieval (#2821) * Adding Digest Auth for webcam image retrieval * Update generic.py * Update mjpeg.py * Update generic.py * Update mjpeg.py * Update generic.py * Update mjpeg.py --- homeassistant/components/camera/generic.py | 13 +++++++++++-- homeassistant/components/camera/mjpeg.py | 14 +++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index 91f44a2a230..91712931c07 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -7,13 +7,16 @@ https://home-assistant.io/components/camera.generic/ import logging import requests -from requests.auth import HTTPBasicAuth +from requests.auth import HTTPBasicAuth, HTTPDigestAuth from homeassistant.components.camera import DOMAIN, Camera from homeassistant.helpers import validate_config _LOGGER = logging.getLogger(__name__) +BASIC_AUTHENTICATION = 'basic' +DIGEST_AUTHENTICATION = 'digest' + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices_callback, discovery_info=None): @@ -33,6 +36,8 @@ class GenericCamera(Camera): """Initialize a generic camera.""" super().__init__() self._name = device_info.get('name', 'Generic Camera') + self._authentication = device_info.get('authentication', + BASIC_AUTHENTICATION) self._username = device_info.get('username') self._password = device_info.get('password') self._still_image_url = device_info['still_image_url'] @@ -40,10 +45,14 @@ class GenericCamera(Camera): def camera_image(self): """Return a still image response from the camera.""" if self._username and self._password: + if self._authentication == DIGEST_AUTHENTICATION: + auth = HTTPDigestAuth(self._username, self._password) + else: + auth = HTTPBasicAuth(self._username, self._password) try: response = requests.get( self._still_image_url, - auth=HTTPBasicAuth(self._username, self._password), + auth=auth, timeout=10) except requests.exceptions.RequestException as error: _LOGGER.error('Error getting camera image: %s', error) diff --git a/homeassistant/components/camera/mjpeg.py b/homeassistant/components/camera/mjpeg.py index dce8ac30440..16897df315b 100644 --- a/homeassistant/components/camera/mjpeg.py +++ b/homeassistant/components/camera/mjpeg.py @@ -8,7 +8,7 @@ import logging from contextlib import closing import requests -from requests.auth import HTTPBasicAuth +from requests.auth import HTTPBasicAuth, HTTPDigestAuth from homeassistant.components.camera import DOMAIN, Camera from homeassistant.helpers import validate_config @@ -17,6 +17,9 @@ CONTENT_TYPE_HEADER = 'Content-Type' _LOGGER = logging.getLogger(__name__) +BASIC_AUTHENTICATION = 'basic' +DIGEST_AUTHENTICATION = 'digest' + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices_callback, discovery_info=None): @@ -48,6 +51,8 @@ class MjpegCamera(Camera): """Initialize a MJPEG camera.""" super().__init__() self._name = device_info.get('name', 'Mjpeg Camera') + self._authentication = device_info.get('authentication', + BASIC_AUTHENTICATION) self._username = device_info.get('username') self._password = device_info.get('password') self._mjpeg_url = device_info['mjpeg_url'] @@ -55,9 +60,12 @@ class MjpegCamera(Camera): def camera_stream(self): """Return a MJPEG stream image response directly from the camera.""" if self._username and self._password: + if self._authentication == DIGEST_AUTHENTICATION: + auth = HTTPDigestAuth(self._username, self._password) + else: + auth = HTTPBasicAuth(self._username, self._password) return requests.get(self._mjpeg_url, - auth=HTTPBasicAuth(self._username, - self._password), + auth=auth, stream=True, timeout=10) else: return requests.get(self._mjpeg_url, stream=True, timeout=10) From 469d09582749849712794d626490afb33639ac13 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 15:06:12 -0400 Subject: [PATCH 036/193] Create initial Wunderground weather sensor --- .../components/sensor/wunderground.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 homeassistant/components/sensor/wunderground.py diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py new file mode 100644 index 00000000000..ac060c455a6 --- /dev/null +++ b/homeassistant/components/sensor/wunderground.py @@ -0,0 +1,141 @@ +"""Support for Wunderground weather service.""" +from datetime import timedelta +import logging +import requests +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +from homeassistant.const import CONF_API_KEY +from homeassistant.const import TEMP_FAHRENHEIT +from homeassistant.const import TEMP_CELSIUS + +CONF_PWS_ID = 'pws_id' +_URLCONST = '/conditions/q/pws:' +_RESOURCE = 'http://api.wunderground.com/api/' +_LOGGER = logging.getLogger(__name__) + +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) + +# Sensor types are defined like: Name, units +SENSOR_TYPES = { + 'weather': ['Weather Summary', None], + 'station_id': ['Station ID', None], + 'feelslike_c': ['Feels Like (°C)', TEMP_CELSIUS], + 'feelslike_f': ['Feels Like (°F)', TEMP_FAHRENHEIT], + 'feelslike_string': ['Feels Like', None], + 'heat_index_c': ['Dewpoint (°C)', TEMP_CELSIUS], + 'heat_index_f': ['Dewpoint (°F)', TEMP_FAHRENHEIT], + 'heat_index_string': ['Heat Index Summary', None], + 'dewpoint_c': ['Dewpoint (°C)', TEMP_CELSIUS], + 'dewpoint_f': ['Dewpoint (°F)', TEMP_FAHRENHEIT], + 'dewpoint_string': ['Dewpoint Summary', None], + 'wind_kph': ['Wind Speed', 'kpH'], + 'wind_mph': ['Wind Speed', 'mpH'], + 'UV': ['UV', None], + 'pressure_in': ['Pressure', 'in'], + 'pressure_mb': ['Pressure', 'mbar'], + 'wind_dir': ['Wind Direction', None], + 'wind_string': ['Wind Summary', None], + 'temp_c': ['Temperature (°C)', TEMP_CELSIUS], + 'temp_f': ['Temperature (°F)', TEMP_FAHRENHEIT], + 'relative_humidity': ['Relative Humidity', '%'], + 'visibility_mi': ['Visibility (miles)', 'mi'], + 'visibility_km': ['Visibility (km)', 'km'], + 'precip_today_in': ['Precipation Today', 'in'], + 'precip_today_metric': ['Precipation Today', 'mm'], + 'precip_today_string': ['Precipation today', None], + 'solarradiation': ['Solar Radiation', None] +} + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Wundeground sensor.""" + payload = config.get('payload', None) + rest = WUndergroundData(_RESOURCE, + config.get(CONF_PWS_ID), + config.get(CONF_API_KEY), + payload) + sensors = [] + for variable in config['monitored_conditions']: + if variable in SENSOR_TYPES: + sensors.append(WUndergroundSensor(rest, variable)) + else: + _LOGGER.error('Wunderground sensor: "%s" does not exist', variable) + response = requests.get(_RESOURCE + config.get(CONF_API_KEY) + + _URLCONST + config.get(CONF_PWS_ID) + + '.json', timeout=10) + if "error" in response.json()["response"]: + _LOGGER.error("Check your Wunderground API") + return False + else: + add_devices(sensors) + rest.update() + + +class WUndergroundSensor(Entity): + """Implementing the Wunderground sensor.""" + + def __init__(self, rest, condition): + """Initialize the sensor.""" + self.rest = rest + self._condition = condition + self._unit_of_measurement = None + self.update() + + @property + def name(self): + """Return the name of the sensor.""" + return "PWS_" + str(self._condition) + + @property + def state(self): + """Return the state of the sensor.""" + self.weather = self.rest.data + return self.weather[str(self._condition)] + + @property + def entity_picture(self): + """Return the entity picture.""" + self.weather = self.rest.data + if self._condition == 'weather': + return self.weather['icon_url'] + + @property + def unit_of_measurement(self): + """Return the units of measurement.""" + return SENSOR_TYPES[self._condition][1] + + def update(self): + """Update current conditions.""" + self.rest.update() + self._state = self.rest.data + +# pylint: disable=too-few-public-methods + + +class WUndergroundData(object): + """Get data from Wundeground.""" + + def __init__(self, resource, pws_id, api_key, data): + """Initialize the data object.""" + self._resource = resource + self._api_key = api_key + self._pws_id = pws_id + self.data = None + self.unit_system = None + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from wunderground""" + try: + result = requests.get(self._resource + self._api_key + + '/conditions/q/pws:' + self._pws_id + '.json', + timeout=10) + if "error" in result.json(): + raise ValueError(result.json()["response"]["error"] + ["description"]) + else: + self.data = result.json()["current_observation"] + except ValueError as err: + _LOGGER.error("Check Wunderground API %s", err.args) + self.data = None From aabeda2b604bc44996d0afc4cc149deb71157123 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 16:15:07 -0400 Subject: [PATCH 037/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index ac060c455a6..ab0727775ce 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -114,7 +114,7 @@ class WUndergroundSensor(Entity): class WUndergroundData(object): - """Get data from Wundeground.""" + """Get data from Wunderground.""" def __init__(self, resource, pws_id, api_key, data): """Initialize the data object.""" @@ -129,8 +129,8 @@ class WUndergroundData(object): """Get the latest data from wunderground""" try: result = requests.get(self._resource + self._api_key + - '/conditions/q/pws:' + self._pws_id + '.json', - timeout=10) + '/conditions/q/pws:' + self._pws_id + + '.json', timeout=10) if "error" in result.json(): raise ValueError(result.json()["response"]["error"] ["description"]) From 1a34bc53015a2e9052ed5701aef48c2a4e11a44a Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 16:31:36 -0400 Subject: [PATCH 038/193] Removed lynting issues --- homeassistant/components/sensor/wunderground.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index ab0727775ce..ebafca9768e 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -1,4 +1,4 @@ -"""Support for Wunderground weather service.""" +"""Support for Wunderground weather service. from datetime import timedelta import logging import requests @@ -90,15 +90,15 @@ class WUndergroundSensor(Entity): @property def state(self): """Return the state of the sensor.""" - self.weather = self.rest.data - return self.weather[str(self._condition)] + value = self.rest.data + return value[str(self._condition)] @property def entity_picture(self): """Return the entity picture.""" - self.weather = self.rest.data + value = self.rest.data if self._condition == 'weather': - return self.weather['icon_url'] + return value['icon_url'] @property def unit_of_measurement(self): @@ -114,7 +114,7 @@ class WUndergroundSensor(Entity): class WUndergroundData(object): - """Get data from Wunderground.""" + """Get data from Wundeground.""" def __init__(self, resource, pws_id, api_key, data): """Initialize the data object.""" @@ -129,7 +129,7 @@ class WUndergroundData(object): """Get the latest data from wunderground""" try: result = requests.get(self._resource + self._api_key + - '/conditions/q/pws:' + self._pws_id + + '/conditions/q/pws:' + self._pws_id + '.json', timeout=10) if "error" in result.json(): raise ValueError(result.json()["response"]["error"] From fae9267701a452bc98793c7c71d239963f549c1b Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 16:41:22 -0400 Subject: [PATCH 039/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index ebafca9768e..038b57b707f 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -49,7 +49,7 @@ SENSOR_TYPES = { def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Wundeground sensor.""" + """Setup the Wundeground sensor. payload = config.get('payload', None) rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), From 75cd1f80635ea6e8b4225a941bed557a54242ade Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 16:50:32 -0400 Subject: [PATCH 040/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 038b57b707f..0ae33a7e607 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -42,14 +42,15 @@ SENSOR_TYPES = { 'visibility_mi': ['Visibility (miles)', 'mi'], 'visibility_km': ['Visibility (km)', 'km'], 'precip_today_in': ['Precipation Today', 'in'], - 'precip_today_metric': ['Precipation Today', 'mm'], - 'precip_today_string': ['Precipation today', None], + 'precip_today_metric': ['Precipitation Today', 'mm'], + 'precip_today_string': ['Precipitation today', None], 'solarradiation': ['Solar Radiation', None] } def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wundeground sensor. + payload = config.get('payload', None) rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), From 4dff42e8bb7280b39f4d9f99af79beab315fc5b8 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 17:04:11 -0400 Subject: [PATCH 041/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 0ae33a7e607..a18397b8cd9 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -49,8 +49,7 @@ SENSOR_TYPES = { def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Wundeground sensor. - + """Setup the Wunderground sensor. payload = config.get('payload', None) rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), From be57cd55c50e0435c602c10fe87dcff00cd47aa1 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 17:25:42 -0400 Subject: [PATCH 042/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index a18397b8cd9..12f581c2e38 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -1,12 +1,10 @@ -"""Support for Wunderground weather service. +"""Support for Wunderground weather service.""" from datetime import timedelta import logging import requests from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -from homeassistant.const import CONF_API_KEY -from homeassistant.const import TEMP_FAHRENHEIT -from homeassistant.const import TEMP_CELSIUS +from homeassistant.const import (CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS) CONF_PWS_ID = 'pws_id' _URLCONST = '/conditions/q/pws:' @@ -49,7 +47,7 @@ SENSOR_TYPES = { def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Wunderground sensor. + """Setup the Wunderground sensor.""" payload = config.get('payload', None) rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), From a0bcd33b71e7b663648c99f8ea50d5078a262be6 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Wed, 17 Aug 2016 17:48:37 -0400 Subject: [PATCH 043/193] Update wunderground.py --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 12f581c2e38..a88f3e1310e 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -124,7 +124,7 @@ class WUndergroundData(object): @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): - """Get the latest data from wunderground""" + """Get the latest data from wunderground.""" try: result = requests.get(self._resource + self._api_key + '/conditions/q/pws:' + self._pws_id + From 244f60d6cd88f7abd65c4f779f96c0b50f33a8fe Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Thu, 18 Aug 2016 03:57:52 +0200 Subject: [PATCH 044/193] Fix script help (#2860) Allow `--help` to filter down to the script --- homeassistant/scripts/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/scripts/__init__.py b/homeassistant/scripts/__init__.py index d737726f78e..af9e00626dd 100644 --- a/homeassistant/scripts/__init__.py +++ b/homeassistant/scripts/__init__.py @@ -49,7 +49,7 @@ def run(args: List) -> int: def extract_config_dir(args=None) -> str: """Extract the config dir from the arguments or get the default.""" - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-c', '--config', default=None) args = parser.parse_known_args(args)[0] return (os.path.join(os.getcwd(), args.config) if args.config From 8088322c43dda6a61dab99ba0f0a3001aa018992 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 17 Aug 2016 18:58:00 -0700 Subject: [PATCH 045/193] Consider core running while starting (#2858) --- homeassistant/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index ccd8a971f61..b77d8356a35 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -115,7 +115,7 @@ class HomeAssistant(object): @property def is_running(self) -> bool: """Return if Home Assistant is running.""" - return self.state == CoreState.running + return self.state in (CoreState.starting, CoreState.running) def start(self) -> None: """Start home assistant.""" From 49998272db832c5365244f7f40bc346708d4a954 Mon Sep 17 00:00:00 2001 From: David Straub Date: Thu, 18 Aug 2016 04:48:51 +0200 Subject: [PATCH 046/193] Added daily temp/precip forecast values to forecast.io (#2846) --- homeassistant/components/sensor/forecast.py | 31 ++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index 1a569d3d4c3..44fe4c2042a 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -44,6 +44,16 @@ SENSOR_TYPES = { 'pressure': ['Pressure', 'mbar', 'mbar', 'mbar', 'mbar', 'mbar'], 'visibility': ['Visibility', 'km', 'm', 'km', 'km', 'm'], 'ozone': ['Ozone', 'DU', 'DU', 'DU', 'DU', 'DU'], + 'apparent_temperature_max': ['Daily High Apparent Temperature', + '°C', '°F', '°C', '°C', '°C'], + 'apparent_temperature_min': ['Daily Low Apparent Temperature', + '°C', '°F', '°C', '°C', '°C'], + 'temperature_max': ['Daily High Temperature', + '°C', '°F', '°C', '°C', '°C'], + 'temperature_min': ['Daily Low Temperature', + '°C', '°F', '°C', '°C', '°C'], + 'precip_intensity_max': ['Daily Max Precip Intensity', + 'mm', 'in', 'mm', 'mm', 'mm'], } # Return cached results if last scan was less then this time ago. @@ -152,16 +162,26 @@ class ForeCastSensor(Entity): self.forecast_data.update_hourly() hourly = self.forecast_data.data_hourly self._state = getattr(hourly, 'summary', '') - elif self.type == 'daily_summary': + elif self.type in ['daily_summary', + 'temperature_min', 'temperature_max', + 'apparent_temperature_min', + 'apparent_temperature_max', + 'precip_intensity_max']: self.forecast_data.update_daily() daily = self.forecast_data.data_daily - self._state = getattr(daily, 'summary', '') + if self.type == 'daily_summary': + self._state = getattr(daily, 'summary', '') + else: + if hasattr(daily, 'data'): + self._state = self.get_state(daily.data[0]) + else: + self._state = 0 else: self.forecast_data.update_currently() currently = self.forecast_data.data_currently - self._state = self.get_currently_state(currently) + self._state = self.get_state(currently) - def get_currently_state(self, data): + def get_state(self, data): """ Helper function that returns a new state based on the type. @@ -175,6 +195,9 @@ class ForeCastSensor(Entity): if self.type in ['precip_probability', 'cloud_cover', 'humidity']: return round(state * 100, 1) elif (self.type in ['dew_point', 'temperature', 'apparent_temperature', + 'temperature_min', 'temperature_max', + 'apparent_temperature_min', + 'apparent_temperature_max', 'pressure', 'ozone']): return round(state, 1) return state From 333e3ba822be4375e298270b086b93e5d5cef484 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:18:37 -0600 Subject: [PATCH 047/193] Add imports --- homeassistant/components/sensor/wunderground.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index a88f3e1310e..051f1f79341 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -2,9 +2,15 @@ from datetime import timedelta import logging import requests + +import voluptuous as vol + from homeassistant.helpers.entity import Entity +from homeassistant.helpers.config_validation import ensure_list from homeassistant.util import Throttle -from homeassistant.const import (CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS) +from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, + CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, + STATE_UNKNOWN) CONF_PWS_ID = 'pws_id' _URLCONST = '/conditions/q/pws:' From b7809675ebd689d0877bf7f17ad508c090031203 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:19:13 -0600 Subject: [PATCH 048/193] Config schema --- homeassistant/components/sensor/wunderground.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 051f1f79341..04ee23e714b 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -51,6 +51,13 @@ SENSOR_TYPES = { 'solarradiation': ['Solar Radiation', None] } +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "wunderground", + vol.Required(CONF_API_KEY): vol.Coerce(str), + CONF_PWS_ID: vol.Coerce(str), + vol.Required(CONF_MONITORED_CONDITIONS, default=[]): ensure_list, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" From a09baf1d5a9819fadf1222ce9438d7c9eb5577be Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:19:57 -0600 Subject: [PATCH 049/193] Not using payload --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 04ee23e714b..73fa69cf73c 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -61,7 +61,6 @@ PLATFORM_SCHEMA = vol.Schema({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" - payload = config.get('payload', None) rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), config.get(CONF_API_KEY), From 53b97feb3cb3ec440959973321efc9906b168107 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:20:22 -0600 Subject: [PATCH 050/193] Rename constant - make valid for lat/long too --- homeassistant/components/sensor/wunderground.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 73fa69cf73c..84fe2bdbe25 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -13,7 +13,8 @@ from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, STATE_UNKNOWN) CONF_PWS_ID = 'pws_id' -_URLCONST = '/conditions/q/pws:' + +_URL_QUERY = '/conditions/q/' _RESOURCE = 'http://api.wunderground.com/api/' _LOGGER = logging.getLogger(__name__) From e4abecd35973528cd8fbf30354ff7f1fa4ccc774 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:22:11 -0600 Subject: [PATCH 051/193] Build url helper method --- homeassistant/components/sensor/wunderground.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 84fe2bdbe25..d5916f99ccc 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -135,6 +135,16 @@ class WUndergroundData(object): self.data = None self.unit_system = None + def _build_url(self): + print(self._api_key) + url = _RESOURCE + self._api_key + _URL_QUERY + if self._pws_id: + url = url + 'pws:' + self._pws_id + else: + url = url + '{},{}'.format(self._latitude, self._longitude) + + return url + '.json' + @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest data from wunderground.""" From 42caa310674702d02867f2339e0359cbf701fb5a Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:22:29 -0600 Subject: [PATCH 052/193] Unused variable --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index d5916f99ccc..4e94249f199 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -133,7 +133,6 @@ class WUndergroundData(object): self._api_key = api_key self._pws_id = pws_id self.data = None - self.unit_system = None def _build_url(self): print(self._api_key) From 1a8e17ce411debf631544d62d99a94c3ed1cc2a2 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:28:05 -0600 Subject: [PATCH 053/193] Pass hass to constructor --- homeassistant/components/sensor/wunderground.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 4e94249f199..b71510792cf 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -127,11 +127,13 @@ class WUndergroundSensor(Entity): class WUndergroundData(object): """Get data from Wundeground.""" - def __init__(self, resource, pws_id, api_key, data): + def __init__(self, hass, api_key, pws_id=None): """Initialize the data object.""" - self._resource = resource + self._hass = hass self._api_key = api_key self._pws_id = pws_id + self._latitude = hass.config.latitude + self._longitude = hass.config.longitude self.data = None def _build_url(self): From 563154c3c2778dd5755933014091f42079f6a021 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:28:18 -0600 Subject: [PATCH 054/193] Validate configuration --- homeassistant/components/sensor/wunderground.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index b71510792cf..0eb9f4bd5a8 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -64,6 +64,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" rest = WUndergroundData(_RESOURCE, config.get(CONF_PWS_ID), + if not PLATFORM_SCHEMA(config): + return False + config.get(CONF_API_KEY), payload) sensors = [] From 62b00e1294a2bd8f8f9fda0194cbcb6c88cd7861 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:29:00 -0600 Subject: [PATCH 055/193] Update invocation of WUndergroundData --- homeassistant/components/sensor/wunderground.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 0eb9f4bd5a8..83457adc06f 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -62,13 +62,12 @@ PLATFORM_SCHEMA = vol.Schema({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" - rest = WUndergroundData(_RESOURCE, - config.get(CONF_PWS_ID), if not PLATFORM_SCHEMA(config): return False + rest = WUndergroundData(hass, config.get(CONF_API_KEY), - payload) + config.get(CONF_PWS_ID, None)) sensors = [] for variable in config['monitored_conditions']: if variable in SENSOR_TYPES: From 31237a891cb297d82de501c5041eb5d3dee05467 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:29:25 -0600 Subject: [PATCH 056/193] Catch exception from update on initial platform setup --- homeassistant/components/sensor/wunderground.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 83457adc06f..40768437f16 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -82,7 +82,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False else: add_devices(sensors) + + try: rest.update() + except ValueError as err: + _LOGGER.error("Received error from WUnderground: %s", err) + return False + + add_devices(sensors) + + return True class WUndergroundSensor(Entity): From 417711d6658d440556e6231ee8a580bd5d5d2add Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:29:37 -0600 Subject: [PATCH 057/193] Refactoring --- homeassistant/components/sensor/wunderground.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 40768437f16..8ec6d54a6fe 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -74,14 +74,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors.append(WUndergroundSensor(rest, variable)) else: _LOGGER.error('Wunderground sensor: "%s" does not exist', variable) - response = requests.get(_RESOURCE + config.get(CONF_API_KEY) + - _URLCONST + config.get(CONF_PWS_ID) + - '.json', timeout=10) - if "error" in response.json()["response"]: - _LOGGER.error("Check your Wunderground API") - return False - else: - add_devices(sensors) try: rest.update() From afef255a25c545c5f08a5f2e665e4b01f43fd074 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:29:49 -0600 Subject: [PATCH 058/193] Condition is already a string --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 8ec6d54a6fe..79548b04089 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -99,7 +99,7 @@ class WUndergroundSensor(Entity): @property def name(self): """Return the name of the sensor.""" - return "PWS_" + str(self._condition) + return "PWS_" + self._condition @property def state(self): From ecb4eb843b9ab65e13f4534d9972007da1b85269 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:30:03 -0600 Subject: [PATCH 059/193] Don't call update on init of sensor --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 79548b04089..e238800c50c 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -94,7 +94,6 @@ class WUndergroundSensor(Entity): self.rest = rest self._condition = condition self._unit_of_measurement = None - self.update() @property def name(self): From dd14f90afb20c7d4d9a390cf77bcc0199503bbab Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:30:23 -0600 Subject: [PATCH 060/193] Error handling on state --- homeassistant/components/sensor/wunderground.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index e238800c50c..c7119dbdc62 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -103,8 +103,10 @@ class WUndergroundSensor(Entity): @property def state(self): """Return the state of the sensor.""" - value = self.rest.data - return value[str(self._condition)] + if self.rest.data and self._condition in self.rest.data: + return self.rest.data[self._condition] + else: + return STATE_UNKNOWN @property def entity_picture(self): From e54ba5ff72068071bce9e90dada17c6b72b1cc0e Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:31:28 -0600 Subject: [PATCH 061/193] No need no need to set variable --- homeassistant/components/sensor/wunderground.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index c7119dbdc62..a3980f4e327 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -111,9 +111,8 @@ class WUndergroundSensor(Entity): @property def entity_picture(self): """Return the entity picture.""" - value = self.rest.data if self._condition == 'weather': - return value['icon_url'] + return self.rest.data['icon_url'] @property def unit_of_measurement(self): From 466dd35f3d0b1b45f73ff9ccdd5078a00798dc6d Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:31:47 -0600 Subject: [PATCH 062/193] Don't set state on update - state already handles this --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index a3980f4e327..1243c55fa51 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -122,7 +122,6 @@ class WUndergroundSensor(Entity): def update(self): """Update current conditions.""" self.rest.update() - self._state = self.rest.data # pylint: disable=too-few-public-methods From d2ba8ee0a7f56c754fadffc0ddde62469cb7a518 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:31:58 -0600 Subject: [PATCH 063/193] Reraise exception --- homeassistant/components/sensor/wunderground.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 1243c55fa51..5c524c3f749 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -163,3 +163,4 @@ class WUndergroundData(object): except ValueError as err: _LOGGER.error("Check Wunderground API %s", err.args) self.data = None + raise From 87f81bf3b48e7dc2a62d5819382b42618541433d Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:32:19 -0600 Subject: [PATCH 064/193] Use url builder helper --- homeassistant/components/sensor/wunderground.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 5c524c3f749..8dc3038cadb 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -152,11 +152,7 @@ class WUndergroundData(object): def update(self): """Get the latest data from wunderground.""" try: - result = requests.get(self._resource + self._api_key + - '/conditions/q/pws:' + self._pws_id + - '.json', timeout=10) - if "error" in result.json(): - raise ValueError(result.json()["response"]["error"] + result = requests.get(self._build_url(), timeout=10).json() ["description"]) else: self.data = result.json()["current_observation"] From 4e586c18ff4bf51401083a5b0dcec80efaabb864 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:32:42 -0600 Subject: [PATCH 065/193] Check for error and pull obvservation --- homeassistant/components/sensor/wunderground.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 8dc3038cadb..979bff40a89 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -153,9 +153,11 @@ class WUndergroundData(object): """Get the latest data from wunderground.""" try: result = requests.get(self._build_url(), timeout=10).json() + if "error" in result['response']: + raise ValueError(result['response']["error"] ["description"]) else: - self.data = result.json()["current_observation"] + self.data = result["current_observation"] except ValueError as err: _LOGGER.error("Check Wunderground API %s", err.args) self.data = None From a5fd04f2155ca7505143359293a5d7718f6b09e9 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Wed, 17 Aug 2016 22:33:39 -0600 Subject: [PATCH 066/193] Unit tests around wunderground --- tests/components/sensor/test_wunderground.py | 138 +++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 tests/components/sensor/test_wunderground.py diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py new file mode 100644 index 00000000000..c6664b71254 --- /dev/null +++ b/tests/components/sensor/test_wunderground.py @@ -0,0 +1,138 @@ +"""The tests for the forecast.io platform.""" +import unittest + +from homeassistant.components.sensor import wunderground +from homeassistant.const import TEMP_CELSIUS +from homeassistant import core as ha + +VALID_CONFIG_PWS = { + 'platform': 'wunderground', + 'api_key': 'foo', + 'pws_id': 'bar', + 'monitored_conditions': [ + 'weather', 'feelslike_c' + ] +} + +VALID_CONFIG = { + 'platform': 'wunderground', + 'api_key': 'foo', + 'monitored_conditions': [ + 'weather', 'feelslike_c' + ] +} + +FEELS_LIKE = '40' +WEATHER = 'Clear' +ICON_URL = 'http://icons.wxug.com/i/c/k/clear.gif' + + +def mocked_requests_get(*args, **kwargs): + class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + if str(args[0]).startswith('http://api.wunderground.com/api/foo/'): + # Return valid response + print('VALID RESPONSE') + return MockResponse({ + "response": { + "version": "0.1", + "termsofService": + "http://www.wunderground.com/weather/api/d/terms.html", + "features": { + "conditions": 1 + } + }, "current_observation": { + "image": { + "url": + 'http://icons.wxug.com/graphics/wu2/logo_130x80.png', + "title": "Weather Underground", + "link": "http://www.wunderground.com" + }, + "feelslike_c": FEELS_LIKE, + "weather": WEATHER, + "icon_url": ICON_URL + } + }, 200) + else: + # Return invalid api key + print('INVALID RESPONSE') + return MockResponse({ + "response": { + "version": "0.1", + "termsofService": + "http://www.wunderground.com/weather/api/d/terms.html", + "features": {}, + "error": { + "type": "keynotfound", + "description": "this key does not exist" + } + } + }, 200) + + +class TestWundergroundSetup(unittest.TestCase): + """Test the wunderground platform.""" + + DEVICES = [] + + def add_devices(self, devices): + for device in devices: + self.DEVICES.append(device) + + def setUp(self): + """Initialize values for this testcase class.""" + self.DEVICES = [] + self.hass = ha.HomeAssistant() + self.key = 'foo' + self.config = VALID_CONFIG_PWS + self.lat = 37.8267 + self.lon = -122.423 + self.hass.config.latitude = self.lat + self.hass.config.longitude = self.lon + + @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) + def test_setup(self, req_mock): + """Test that the component is loaded if passed in PSW Id.""" + print('1') + self.assertTrue( + wunderground.setup_platform(self.hass, VALID_CONFIG_PWS, + self.add_devices, None)) + print('2') + self.assertTrue( + wunderground.setup_platform(self.hass, VALID_CONFIG, + self.add_devices, + None)) + invalid_config = { + 'platform': 'wunderground', + 'api_key': 'BOB', + 'pws_id': 'bar', + 'monitored_conditions': [ + 'weather', 'feelslike_c' + ] + } + + self.assertFalse( + wunderground.setup_platform(self.hass, invalid_config, + self.add_devices, None)) + + @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) + def test_sensor(self, req_mock): + wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, + None) + print(str(self.DEVICES)) + for device in self.DEVICES: + self.assertTrue(str(device.name).startswith('PWS_')) + if device.name == 'PWS_weather': + self.assertEqual(ICON_URL, device.entity_picture) + self.assertEqual(WEATHER, device.state) + self.assertIsNone(device.unit_of_measurement) + else: + self.assertIsNone(device.entity_picture) + self.assertEqual(FEELS_LIKE, device.state) + self.assertEqual(TEMP_CELSIUS, device.unit_of_measurement) From a5f144cb7c3f090b97a2f9751ac6467bc89f1fa5 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Wed, 17 Aug 2016 22:34:12 -0700 Subject: [PATCH 067/193] HTML5 notify actions (#2855) * Add action and callback support to html5 (#2855). Remove registrations from the callback view since we always get the latest anyway. We dont put an audience in the claims so we will never hit this error. Bring tests back up to where they were before callbacks. Only import jwt where necessary Fix bracket spacing errors Fix JWT decode check for loop Remove stale comment. Add tests for the callback system. Shorten line Disable pylint broad-except and change e to jwt_decode_error. Verify expiration Remove duplicate jwt.exceptions.DecodeError Catch no keys matched and return False * Switch to using registrations for callbackview instead of json_path * Only check for URL and such if the data object actually exists * raise instead of return * cleanup decode_jwt * Clean up JWT errors * Correctly set status_code to 401 * Improve JWT by adding target to claims and attempting to check the given target for a decode match first, as well as pass the target through in the event payload. * Add tag support and fix formatting issues * Pass through any keys that dont apply to the payload into the notification.data dictionary * Remove stale print * Pass back the data dictionary if it exists * Actually put the default url even if a notify payload dictionary doesnt exist * pylint, flake8 * Add subscription validation * Add validation for the callback event payload and use constants where possible * Use HTTP_UNAUTHORIZED instead of 401 * Change callback dictionary to dict instead of cv.match_all * Fix up tests and make subscription required * Whoops, that test was supposed to fail * Use the result of CALLBACK_EVENT_PAYLOAD_SCHEMA as event_payload * Add a test for html5 callback decode_jwt where the device has been renamed since notification has been sent. * Remove the loop through logic, assume that target is always in JWT * Always return something instead of possibly None. * Update frontend --- homeassistant/components/frontend/version.py | 4 +- .../components/frontend/www_static/core.js | 8 +- .../components/frontend/www_static/core.js.gz | Bin 31500 -> 31529 bytes .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 123182 -> 123194 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2012 -> 2285 bytes homeassistant/components/notify/html5.py | 220 +++++++++++++++--- requirements_all.txt | 3 + tests/components/notify/test_html5.py | 109 ++++++++- 11 files changed, 306 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index ec30e4804c7..82d10fb5f47 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,8 +1,8 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "b4ee3a700ef5549a36b436611e27d3a9", - "frontend.html": "411fcc6c69b3cab0740ac3db4b9947c8", + "core.js": "7a72f4dcf2a1d5e04094ef807478614d", + "frontend.html": "77a461848fe2a94da4e26a103bd6f814", "mdi.html": "b399b5d3798f5b68b0a4fbaae3432d48", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index 4def07355e1..8b529c77424 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&&"object"==typeof t&&"default"in t?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 De({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ce.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 Re({authToken:n,host:r})}function u(){return Le.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 Pe.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?Be({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||Be;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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c199&&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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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(n){}}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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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(c){throw A["default"].dispatchError(t,c.message),c}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var h="Store handler must return a value, did you forget a return statement";throw A["default"].dispatchError(t,h),new Error(h)}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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(o){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),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,t):(this._twiddle.textContent=this._twiddleContent++,this._callbacks.push(e),this._currVal++)},cancel:function(e){if(e<0)clearTimeout(~e);else{var t=e-this._lastVal;if(t>=0){if(!this._callbacks[t])throw"invalid async handle: "+e;this._callbacks[t]=null}}},_atEndOfMicrotask:function(){for(var e=this._callbacks.length,t=0;t \ No newline at end of file +this.currentTarget=t,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()},i=window.Element.prototype.animate;window.Element.prototype.animate=function(n,r){var o=i.call(this,n,r);o._cancelHandlers=[],o.oncancel=null;var a=o.cancel;o.cancel=function(){a.call(this);var i=new e(this,null,t()),n=this._cancelHandlers.concat(this.oncancel?[this.oncancel]:[]);setTimeout(function(){n.forEach(function(t){t.call(i.target,i)})},0)};var s=o.addEventListener;o.addEventListener=function(t,e){"function"==typeof e&&"cancel"==t?this._cancelHandlers.push(e):s.call(this,t,e)};var u=o.removeEventListener;return o.removeEventListener=function(t,e){if("cancel"==t){var i=this._cancelHandlers.indexOf(e);i>=0&&this._cancelHandlers.splice(i,1)}else u.call(this,t,e)},o}}}(),function(t){var e=document.documentElement,i=null,n=!1;try{var r=getComputedStyle(e).getPropertyValue("opacity"),o="0"==r?"1":"0";i=e.animate({opacity:[o,o]},{duration:1}),i.currentTime=0,n=getComputedStyle(e).getPropertyValue("opacity")==o}catch(t){}finally{i&&i.cancel()}if(!n){var a=window.Element.prototype.animate;window.Element.prototype.animate=function(e,i){return window.Symbol&&Symbol.iterator&&Array.prototype.from&&e[Symbol.iterator]&&(e=Array.from(e)),Array.isArray(e)||null===e||(e=t.convertToArrayForm(e)),a.call(this,e,i)}}}(c),!function(t,e,i){function n(t){var i=e.timeline;i.currentTime=t,i._discardAnimations(),0==i._animations.length?o=!1:requestAnimationFrame(n)}var r=window.requestAnimationFrame;window.requestAnimationFrame=function(t){return r(function(i){e.timeline._updateAnimationsPromises(),t(i),e.timeline._updateAnimationsPromises()})},e.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},e.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},_updateAnimationsPromises:function(){e.animationsWithPromises=e.animationsWithPromises.filter(function(t){return t._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(t){return"finished"!=t.playState&&"idle"!=t.playState})},_play:function(t){var i=new e.Animation(t,this);return this._animations.push(i),e.restartWebAnimationsNextTick(),i._updatePromises(),i._animation.play(),i._updatePromises(),i},play:function(t){return t&&t.remove(),this._play(t)}};var o=!1;e.restartWebAnimationsNextTick=function(){o||(o=!0,requestAnimationFrame(n))};var a=new e.AnimationTimeline;e.timeline=a;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return a}})}catch(t){}try{window.document.timeline=a}catch(t){}}(c,e,f),function(t,e,i){e.animationsWithPromises=[],e.Animation=function(e,i){if(this.id="",e&&e._id&&(this.id=e._id),this.effect=e,e&&(e._animation=this),!i)throw new Error("Animation with null timeline is not supported");this._timeline=i,this._sequenceNumber=t.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},e.Animation.prototype={_updatePromises:function(){var t=this._oldPlayState,e=this.playState;return this._readyPromise&&e!==t&&("idle"==e?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==t?this._resolveReadyPromise():"pending"==e&&(this._readyPromise=void 0)),this._finishedPromise&&e!==t&&("idle"==e?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==e?this._resolveFinishedPromise():"finished"==t&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var t,i,n,r,o=!!this._animation;o&&(t=this.playbackRate,i=this._paused,n=this.startTime,r=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=e.newUnderlyingAnimationForKeyframeEffect(this.effect),e.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=e.newUnderlyingAnimationForGroup(this.effect),e.bindAnimationForGroup(this)),this.effect&&this.effect._onsample&&e.bindAnimationForCustomEffect(this),o&&(1!=t&&(this.playbackRate=t),null!==n?this.startTime=n:null!==r?this.currentTime=r:null!==this._holdTime&&(this.currentTime=this._holdTime),i&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var t=this.effect._timing.delay;this._childAnimations.forEach(function(i){this._arrangeChildren(i,t),this.effect instanceof window.SequenceEffect&&(t+=e.groupChildDuration(i.effect))}.bind(this))}},_setExternalAnimation:function(t){if(this.effect&&this._isGroup)for(var e=0;e \ 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 41c7c071ac75a40a401361571b9fd1358c21cd49..e1c641e3169560539be5957dcd7cb747ecbc277d 100644 GIT binary patch delta 6526 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 delta 6514 zcmV-&8I9(;!UwLx2L~UE2ne4fuz?4)2LWEPA@z_=Yt^=UtP8)+a?jqLTEQrjC8^pZ zi_0P{d1*%Mui3YTvH^nx0iTx&w*mbcUyo27$!=$3IBv|ltCSzTch6(!)T>X$|0=g3 zxB(*r0nN8Xy8&?l0UfuuyaBoa0kOAoz5%ra0jReq!vUTF0Uwvg!~rB0fBsU?>nsG4 z6)DgAob;$@(`weA{tcG_#Q~B5Z?}}i0SW_uS$jXyRsWH4nZy7+Xv(9Q<91=wUVVU- zY>K;ne^t*5X&$;6|HT_7Lra=rV1YPNXV~D9Hi@b8`|`4BhHx`@G}OXvp6Z`n7dIcEJMfjLcmPpK4q#Ti#rZ6M z(wnBsVX#wh)wVD!Q(i1fw--LBbj!<9v`T*cGzUg1n^sl1YL3&C)1m37<&TV$-55_Z zBK=k@sP>~nxm(XWN(;3cztp$6B67WXPsb})1e%E|y+11E-ruP>PrlNfeb&dS8DKY- zi+oCF=Ba{tY~eNb*8Mt?O(V0v^7#~hOYJS1n8c8(n*y5$E{EKy+ksF9k4u!|%gG%W z{e5;9HnCILlAwk*tbcocY&S3V?14Ya7Q2qQK`c0l$ZObMwb)0ThZd~pwB`me zAWpSa{Y^*LjySj;7zfw$bM6qwOUpRCn&0KQ&Dk3^IcN=qERDRaMqka_9dE3ENVa#M z(I)9GNb?)_kiM~%7qZ6gYEGSTf%`0I7J15E2F87EV3!V)qa%EaZmrR&jehoH=0{Bw zv$&!uo}$K)KG&~SO#Bp|EYt1p-CW|C$^h>U&FKn7gonF!!lpz^sA`tg533&@!mq(n zLLc6wKy#!9K?V1@IwxqcY^t4qq^W*`nF^)?N^7LeI z_UYu)tF!KTJmdKX$L$#o-H0$2zD#lVy{I-{i5RWINgA5nmu_$p;#Pcr64Se{>T$C; zyz@PW%cllT5U_502%o?Nycybu9p#@aKpOM>BpIVsWy2EY&V zPW(Qi>og8*I2@598x2_0z-}^uwI=Tpy*0r^p4@{7wvDMgyAu^_C5bjYy%Qz1%9zT} zhj*gFD^M_U`0Va9V4f0xk;9{>_vl`+b_GA3!@CWYxv~XUohMtj4Glt3#|73jHe0zm zjUAveuN@$TKQx;^)?A$JWG>E<^VnR)WEWP?c2Mm4gdK^b^4ltH7~aJ_77Y)PMz~WEwjx1~d zv3N{Mqr>(V-M!K(X6;;?+jb^2Pp^QkWYg>oWN6B0D~6#b5MWaqpY@J*tnANS@fXYk zMNf*zT4J%#Ek)kJ0wtkA!yeA9NI{VSkDMZdGIpD?^qk&d!BY3SE}Z_Nw`W;}zkg@3 zQ|Ik&3=GWpUpnxAujgCk7VswIsj^M}^Xwv7>}}*kn7*z4;8V_kGsKBF>2w!#-{PE_ zeHS5bs|{6QC=yVCqgizKOeJLPRBF2=8opG2X-iW^&j^~th5ogee?i|rQ4InCWyxO0 zA#J-<28m;qjpRq<>=~$l^Lb*TQOc=<0|x!oo)v`5j=bhulV^A!+onGZ&6Y#{!+@`uET}$b_jvyphq5cA6+4l@g zqki38%*HD``#_sP|8EHt0XywH-2uvr{qZ%t!&AD4XfvG_y{9+dA*#Cpe3UP3F-G24 zzSNgm1AQZZuR)AUN0(HQYcXb6Un(ykefb%QghiJc^7tyh?0rtl?CFz#dwuXQL>`bDRkhHmmZ^G+{64Ndteug!jG_jLD#=478U59<_OL? z^I(d9xxatEQ%`I+nCUp3PX@xg3R=n(^zaV0>>SNxhHj`9dJP2HDCq^T49nVB)5x^b+xkJ;6$+nEkz6^W2vpw^{rkh!3L zPd3-vnNoH2wyg%!2Mh(4sElU6_C>TZhl-O~^ld+eG0a8-+yM*&3G5A=j&FSJbe>Ew z^{mucMz2)tMBw@A3Om%Z^af_+?wsscXJ}^kL(Ngyy}2FC{s6WyM|#(v;90CNBXGtT z(gSP?M{4Y1il~sx+mOWnQ}1siDunKTwnS;@YKYb!ic)bXN+0S_6qL&to+bQ5-C(v4 zGG+HC=@gr7d#%>c2$XA8K1JC0Rsd#Y6Be2wE?g|Kot2@@^j!_fRd8xH^53V}IBzS* z5Do&sAK{zC$o%A9Um=Wn(lwu#h#mKTRS zDt#jN(DJojz~n-}4d{WTr_XrEU$(3oDU677H-V5RS>f(K}&%iFI+4s+Ol?TTtzjJb7NqlzBDTxRUK4P7EaY5Dv|%5SK86vBB7 z9yJ1nKyy7joZUtUpb>Qt)z$aIvEar;SfqJzvohj%MV$w54i5H;okiCk-vMAOwA)EE zB?BTOm`xxmIZ$K*VN5x=g^C)DaWT8@ghm#0d9$bScAfTGMl?DiM!UP}7nU zXiF*}>+JG+O>RknB!Eq06UJrYj_dXqn3;@VR|RC5)c{#SwK$QtC?^&EEF_uP-AQ(I zKbR-%Foa)`9r3nTk!T&*HQ75S*Jn?Xeog*x-8zrKfkV{gL(5iw;o_wxN53Lpg`*UG zH|jMANgvxE?E~m8<44>21RBtkv66*JY{7!YO6N^tN101vrGzB0vCHlPUaA~OY_E}C zt#6XSpzl5OIvdZ>*~SMrweU;Vipij=druB!r`5BkyLKi2WX8NbF2IgNKiG(PnxvX_ ziM)!;r}fN*aZ6KwV$a!~?!ujvLw96O&DNFtlUWPN{(xs*j9{@Cf{a|@(WF+*s+{B- zUFM_=tY=;30@mf9mhW6>_q%5c>~*`b9kx8JZ;hQ7+GHnKEpzwNd$vkToXyURN=nza zM(0DnM)gCq!YkxhMi&od4P|8vY2FC}*tVf=jI%+fmj_pW{h+%DX3KZiA~RN77~}de zS>xi3U@zN8;M+CQ-olHtXNT9*ZC|XnG*6H6bX;6n25L^KxxV5It4nB53)KM%xwH;N zDqqbC0ec|h!}b27McPUCVC{#4Pyzu?~~f z7B>VP2#9O_vpzgld0pIy@a8WhcrF+#QM0sMpY>B|uEp$edmwS{VvLVEz z8EnZKrU1%=vQHBd(Y!KP1HKhH$RYhH$Ry+C#KCio4XhDTu5f znfN95_CVrdl=lmYTjbA>&C!eeGL2D&Ue%+QYB?s6qHS@6xjE2L)z@vJGnu`gnFMr@ zrVx35x*0CrMYn5(9DYaFqzJJOGwktP0lF&dv8TW~Ml*5nuZ!h)^qcWvS619P0L%nt z!Pz1mXPbGs+0Zf4)hrNWDp0r)=xM`CogDGxWT~o1bFA~~wd2jX>gT;-OxwS-wIFJ9 z4X?%&IbFW|;6&p=U0}I{0&e<`+PuCE$LSP*iiw*Wv}RvTdinnC$?3bZ!M~nSKlm*ed9_dOcA^ zyQb$db;cK`nGFdWtmcUiNZsse95FK=1`hG2o~^zf*RbNv&``~Ls#jI_H)>z_l%-mK z_p*0K8Q)OwvUg&4Ap&s~I|t1Tfd9}hLr{VEdF_tMuX|lCqKk4kd!fLxp80c!P+TF4 zgj4OB@i+xLwB!M zm-#du>w%}P#4izLP;GW62u0p@6IImj=zss`f7v%Pch_R87TJB3+52vqa+H;u> zH%1dZ^NTbLqNs?QtT$uxK;oA*tvr<#nAWkWZrS(m)7t$KI$=+m=?oT4<$?M}Zfp4Z z9ufYl*$mUxEFAk=dRMtwS{gy^Mrh!9;eEWd0k+$ZKjZ89fe`{nU)={?7Nvut&ekg7 z42~evn4zrjSNxZBHXDCyv|4Y*bgqlH)aB=EP>8*c$cUdP8{Jf! zHt*?o;f6O%;c=-OPjzrig`=mqVFnnZOikNWE+45a3?Uz4XIpEDolKc9NJoNwMbYD6 zLdr-%qFn#fe;Fefkl^m@FeSIh*#3ZdPT{MP-{y3)HVJ3$@tah_XGI`?$~y)HGkxY| z;CIrE0Q&ke&hO)wzT52h!mc#zC*pENpKK>^Bi) zv^vnI^w|(oKjW17DEpl55YKGOpop9%m4Ax6&Wo}ot0Z^x?l$X* z4?{P+aF042*UaCugJY-zM7mrQz1E~`ElX6IIVcf@HwI##zvPR+he`1tUg{boGEDno z3|y~FUY-Ci+wlLnm}A5}8FX-V8)=0Y?bWt&LKk*_){cN(d3#e=hL#iP z8S9?6b#&F!_%OqPFoiY|=>yoc-VKbh%XB$jsP^*HfgT>juI3o6swJw;p5Z^L=7V+5 zZC0D6i>zi<*@D`NYv@O9B1MO0wZWPbv02ZNSzcG;76FZ_&;Z#wcsA^<6n|UnJum?R zorGf}PS;P+Gd?tbP=b&dO_HDIS2e0F^c|=?oI}RSl$>T?X{MLTOTQC6+d8(T+SiN) z!`cek;#w5L5^tCADPnXYQ3fo}!Z1)X>{efKIM7sJZBWw`}x3tGA#c36o1v>ToT>dR8Hl_;j3$z%w%EsY;rD-U+#7r;7B0!3+rO($S zrEP+civTSfhMq8+m5w@Ko$BR$jh~+pO>um;`h*>9H@opls4?WRY!ItHxb!v+WPJnI z%5sh`E-BFEhQ^8l!LX(kEfz&+!YRW=pyh`0vhzssVpn>%__@WvWw$vQl3)P0Yt5VD zDtfErCCRcwVUy3HG^c!Db$Qa>nf-fzT^+lIHjaTjMyUEW+}RXTVm_G z!(z?QnJh@T9zTDHpi-zQN1sq~`+1d6uLZZRm%tc*Q*@EpD*)*Vf1fzGUUo<1$G4+E z=c)|Ugi`FG>cQ}M1#}99cyMdVzS6^ohpFi@hq-t=8T-}9srXPep*H}&zJ@i{f>FjZ zuU{!<+NHv~y5Ji}i~FAQXhXe5kUGaHUGKEYAzj9TX1%~IP=+#ZwpmVr&nxOzd9Gs{ zK5d78=ynXpIo=Zm;gk71{kDPbd5A7kNrGG~ivNBF$2oLeFywU5z8&M2x9K#!g6W-0 zFxCD2hQN737uHcRT;f3ulvb9@81QycfHM01JHA^^$9P-|=fp2lXg5Z(btQ3_A#(#T zIf}35paJqLZ!=FDCd4EM4Y8QkxZDje;L(VGo#ZHRq=<;QG*XP)KnVG z=EtprZgG6j&6vCAQ~s|``9-Ec#tyP;uC%Uy&&yG#8nM~yBFMBqKnY$e8)C;A1n9?x z?UW9^euN=pF&yrRbbM`?dU>-q-QVBKd(8#pnx*6b!j23Z$|ciQ3(JZiSlBq47md6r ztuuIvsDR}gj*BuQjVo?S!9vBY2IZH3jZ8W43gJVkQeDJ%EKMqB}wmB{G&ZKzKxgRCGhMqB#*Fa32M*l+hx86H*V) zy|^uX&KfH;=Lp!I_tWvW?jB6)wJIi@DyBX+?7A(p8SO%XCs!yD7sVS?A=trIIiJKh zMJ|imxcR(waIAiH;~}(cA_K6~fTDl&$t-WgAKssRij#PXGVojbdNCOvp|3W#g2I4y zv*a^$4Ae~yyC(V!kXe}GM=_6o12oCX61rr6U;U{Wy&6siWd^_IgB-e&ywi{44}=W} zeZE-EU_xe*$yJ0J04f^o*cR(zP8hyf-d5v8nPW$m&`4(OwRB?gq{ap=_q3s_==Zb4Qie^A%U_fwC1j#R-=q=l%OKn}3Vw-~HHd9f_X( zGy0Ci{0Ufw`3bu-9Nkzmr!>=M6W@;gdx@W&*= zd($)4KnWIho|Uie}A5i^Tt ze$A-1Qw9536ct@NgW)a7WQIfnW+_;!u)xM+G$M**iW5v7hR^Pb@mK6F(`03+tOThb zKDE?y5?TB!i%L2Vf>NH2$qBp^_i<#M+NNPN0JK3$hi@?&@-E4LpslO2TOjVA?M6LZ z-8N-8AF20^*X4RD?sx(U$bC@6#C&m~*_z}nOoG?Ba-rTyEt9)+mz=c5- zFU`i}2mv3uD}1%dZ~kE)!oSJno0y7Omw(U)db2$ZDsD#q8SuG(6~rlvq@GB(Qc1>i3E5B|D%1XGRJ2gg4RZl>77IAT*rmlBMdQ!c z>~xwh-j-Jla|@?S#^2}TGj!L~2P{J%SGvpWp}$P#*J%U5zch?kvdS1W*6!Oa&{ED(&LQV|_pQCM1PXaGfx5+qk1!yv^-=p(b6?Mz3Oh z>;F>GS&NE-R5i@(IP}?bN)t~Zs>a3eE^~q33j@8qFyo-OgI-x=Z^2xi4y~9od>$zJ zo|}Q@%W=;^=0hjDth|Qv3mhhK^UsHmC!@R-Khnh?#dI);lOplRhl{KH1*ziU2MVec Y?$ZBUjK1MA1RBr(50l`&S2mRg0QWh{kpKVy diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index dd6ee9544e7..2c61fb2b72f 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit dd6ee9544e7129b1735fe2377311ff2e2b7449c0 +Subproject commit 2c61fb2b72f422155dac4e7308181f7f7f845f44 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index 40e47f06969..58c4b528f05 100644 --- a/homeassistant/components/frontend/www_static/service_worker.js +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -1 +1 @@ -"use strict";function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}var precacheConfig=[["/","9a5d0507bd1f13e3eca6b35abd4cbebb"],["/frontend/panels/dev-event-3cc881ae8026c0fba5aa67d334a3ab2b.html","e22ed0d2d10777c87eb9620d81f525b4"],["/frontend/panels/dev-info-34e2df1af32e60fffcafe7e008a92169.html","7e939dc762dc0c0ec769db4ea76a4b09"],["/frontend/panels/dev-service-bb5c587ada694e0fd42ceaaedd6fe6aa.html","782c4860c5e8ab274231ba9dfd528f29"],["/frontend/panels/dev-state-4608326978256644c42b13940c028e0a.html","26758b741ac1b7c8e9cfcb24762d8774"],["/frontend/panels/dev-template-0a099d4589636ed3038a3e9f020468a7.html","99114026cf9193263c74cc25f9f6a469"],["/frontend/panels/map-af7d04aff7dd5479c5a0016bc8d4dd7d.html","6031df1b4d23d5b321208449b2d293f8"],["/static/core-b4ee3a700ef5549a36b436611e27d3a9.js","e2fb4f1dc0d1e8192a327b51768b3802"],["/static/frontend-411fcc6c69b3cab0740ac3db4b9947c8.html","5967b9cdaeb14753552c2461805eb397"],["/static/mdi-b399b5d3798f5b68b0a4fbaae3432d48.html","819d479ae2b690589687469045b22c26"],["static/fonts/roboto/Roboto-Bold.ttf","d329cc8b34667f114a95422aaad1b063"],["static/fonts/roboto/Roboto-Light.ttf","7b5fb88f12bec8143f00e21bc3222124"],["static/fonts/roboto/Roboto-Medium.ttf","fe13e4170719c2fc586501e777bde143"],["static/fonts/roboto/Roboto-Regular.ttf","ac3f799d5bbaf5196fab15ab8de8431c"],["static/icons/favicon-192x192.png","419903b8422586a7e28021bbe9011175"],["static/icons/favicon.ico","04235bda7843ec2fceb1cbe2bc696cf4"],["static/images/card_media_player_bg.png","a34281d1c1835d338a642e90930e61aa"],["static/webcomponents-lite.min.js","b0f32ad3c7749c40d486603f31c9d8b1"]],cacheName="sw-precache-v2--"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},createCacheKey=function(e,t,n,a){var c=new URL(e);return a&&c.toString().match(a)||(c.search+=(c.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),c.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,t){var n=new URL(e);return n.search=n.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(e){return t.every(function(t){return!t.test(e[0])})}).map(function(e){return e.join("=")}).join("&"),n.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],a=new URL(t,self.location),c=createCacheKey(a,hashParamName,n,!1);return[a.toString(),c]}));self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(e){return setOfCachedUrls(e).then(function(t){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(n){if(!t.has(n))return e.add(new Request(n,{credentials:"same-origin"}))}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var t=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(e){return e.keys().then(function(n){return Promise.all(n.map(function(n){if(!t.has(n.url))return e.delete(n)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(e){if("GET"===e.request.method){var t,n=stripIgnoredUrlParameters(e.request.url,ignoreUrlParametersMatching);t=urlsToCacheKeys.has(n);var a="index.html";!t&&a&&(n=addDirectoryIndex(n,a),t=urlsToCacheKeys.has(n));var c="/";!t&&c&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(n=new URL(c,self.location).toString(),t=urlsToCacheKeys.has(n)),t&&e.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n))}).catch(function(t){return console.warn('Couldn\'t serve response for "%s" from cache: %O',e.request.url,t),fetch(e.request)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t)))}),self.addEventListener("notificationclick",function(e){var t;e.notification.data&&e.notification.data.url&&(e.notification.close(),t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var n,a;for(n=0;n|{D)TQmsX$GMMl0dLd6 zsIzUUtT!{8TG_IxM;+J~=DAQy&~MwS^C9@ug59+B2%?X0*ZDzYmr(n=4~{mh#QNzM zo3^?S?$3W(!|mubSX{wvdt2(pmZns~{pZIUsO@u6RZ^&rK7=;-WXcv^Zo1`u^^@qo zyR^~p5Ncrs{_jvuU=I>s@+cy{@*7PCs-_?Skv1Zwl_;p*P@21n`*e3fQ$JgRw~b_fSj;Y z5hFz+M4IV1<{}o7$sPsN1B`(tnrTY1EJN`iilT~g*e295MWfQm@$kP|C+2{K$n}< zR+s^bA)y(`XrY+F+Da2b0h@r-fU>_P>=i6Fm1wupgo;gu$(%?jOhSv)2uTwma}7C$ zTOCR(UEiJ>apN8)v|zvC-)LPgP!6X>fpN|eA~Z;3z_5W)DWM>g(kwYEC&GVRN?^Gs zQi}|=f^!QbRTAT<(gN$}2%>T&7SJIPwEF!Dp%L$~EbpLwFBe;DM9f)EHB~f^F>SCs zQ_j$oA|{YhAr7V8f>h0F-PG89yGd1AB=)i%%0LqAk3wVJX1q|GV5+59at47ZbS|lP zeI523@T*wC-0N;9J5re3u*t-`@H?nX)WV`f0_hp%yOWiuQwAyF2^?rIC3a$T&gzV_^?x$MAZ}W#4!|}2sCoy+4`1aM$$XByr z>_B=#wiVG@*kz5X2#G@?yS!{LUMD4u%V;RiokUtDm0l0^{4@!kc?f zy%9kWsv~pD?j`#2Zi%6+5M|Jh@F|V&1{K(jCBb0qGcr2{&IWr-X8X~uYgX{oNGGDP}+dVeD|=86%C>e=NIcEQo;H8bGv8mxgpe)6>5HJqm6Ln zXzw0g+1;yW*twv?0riSp2mL5}R@aB7taqx0XEg0m{wzhe>@gV1iRwiX1zSDyM8YJ*(Fttn0h77u{e%;;h|*^-HOt_t!-KPy$4-{^MsfaNaC#hh zv~?e$(aW}3l^sN=-v7RB#a)Cnyz(ER8Qq9#19*&i6hYBf0frf2a22!HgsuBnuHPXdLo&Dz!ZUEXbIc8f z=@`!;(z`R$SqEqT2kvJMd*Vs7#h0LTXTJwHue{+<<6Yyn--DH^N=HNZE6UYZ(CSY} z$55dm-rs(F{=oI0 z@i6(>b%pBl_H^?8wrM{?i){aSCF;^RS?*Yf^%DH~PdFwVLDCcDzRRdbUFNWBob@QQ z?iAcYhwP=_m3H~ZQ*|Jk$MP4@Q{jDZHSH6|KVXeLU{w)+g_8no008Jiu-Zb zBM&zs!Iuj1@D>FN*$th~p1RBGXP2;^VXk0NkeT?)ZlIcpi;DnTQH{JTke8i8tX5R% znMQ3oY!0J(*CXqwU-N?*ez7yd6~nt;^={kg8~=}m1Mxc!#}@;EyZboY2ebbHjt;O^ HITQc@4%&EV literal 2012 zcmV<22P60&iwFpyB(PTk19N3^c4=c}Uw3bEYh`jSYI6XkSZ#0H$PxZ43ei)@nxglO zFB??|uIZr&n%o7s3-TfL8T&FTF`<<(saSpt-a~W+K*c3esQmqS%Ce}RBZ^+*9N+E<42Huftxmrl5PP$+-*2muvDw# zFV;=h6Qyol1Mhea{iFVQ~6T%3lDVGAHW(ANtKP=1BLg#`i zLp1^i(m11;=#N*LTIKhazenRsgR0iTJS8R6d1Bh$>ei8u*+%TDCXQ!D5zwL zvs|Y%&kD_vng@1w2bc&-oiUloq~=Cxk_(~?N4jV!1wy@xI+aj(~XJHGK zOB$G$sA8&Dl$Vd5B(14e@FEDJxSV^eQ53azszHk#H0@i}nMLVQU(SDDcgxH3i&$Cv zj}rZKb#wFDTliykFIRCFeeK1`&w9Q3@cs?z)pVm^C{MH5%qJ_=Ej(IJ+6wz~IHA#a z9Ns@Zn{`p_ldk?1b=S|s=v!wF>? z(J&RA^!2$e{m#|q9z%P;pM`1{0|uKix!kLhAjY|?{jJ`Ss~ymIi{1{$t49I!&~>vu zz}Vx3Vp-g0E*^@ks?AVf$dB0}g+p~16SDXj-J$9HjxUIXFoDXu2tE6@LgGj!wK31>)VHSjpFo-`FOH@u=FlNqjyccEL%v>efVS3 zsG9_3co{xGGr3aL8gL?hkU>9G0j3#Y=quEGC)xHQ? zjDJ!$<-GI(0yF$P8k+acgRr$<%GF0iWJ892Lwo{Gh1;(%O^0}HGQAtWPabgkf8c)N zyTKnt+dlF24hn1MD`3IAIjQKY#iy7+PDi$zOtP zXHnZNh*&8nJ5zYS2aoWS5=GN)_Am<@8VwCp&9E#`lr}Tj^jS9^t6pGck7O(CwIe=d zY-7#LP__mmW;_l&&J6ROActo}Nf?hGb^Y*D@Ov1(d=_qm{#LEZ+rA}Kx7$yX%j>%N z0u4(2?Na&D^|n5@*e{|a`s-hCMmT_EP|3R%V;;1a{g!d^L@^$tx7ng}*^gzn_}_WD zQJIJK=P>9X^2-eGkMxUv=Blf{Mj9VJe^sw5>;L_{8}(SgXcH5DY`eM{1wXXGsP87D zA*2_hAAWg$hy`j_JTUN{H3MBw^L4du7e~q(i`J^H=Lh!k;daOXg1BGJM@FVaef@LY zm9E_2AEIEDUDb=~Q&r>lwqUiHFULdLU$%|!$ip584E(_xQ`IdDBsj5ULxR0lwXOOg zvp-^g`P$v|Ot6?7T6 u+N@hF&5_!*CzTA(!f1*+c472X{5ZJYEqnYX9I}nS)Bgh1c&Hko5dZ)>6XA^j diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 33ebe8e0c0d..6aafec8e120 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -8,12 +8,14 @@ import os import logging import json import time +import datetime +import uuid import voluptuous as vol from voluptuous.humanize import humanize_error -from homeassistant.const import ( - HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR) +from homeassistant.const import (HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR, + HTTP_UNAUTHORIZED, URL_ROOT) from homeassistant.util import ensure_unique_string from homeassistant.components.notify import ( ATTR_TARGET, ATTR_TITLE, ATTR_DATA, BaseNotificationService, @@ -24,13 +26,13 @@ from homeassistant.helpers import config_validation as cv REQUIREMENTS = ['https://github.com/web-push-libs/pywebpush/archive/' 'e743dc92558fc62178d255c0018920d74fa778ed.zip#' - 'pywebpush==0.5.0'] + 'pywebpush==0.5.0', 'PyJWT==1.4.2'] -DEPENDENCIES = ["frontend"] +DEPENDENCIES = ['frontend'] _LOGGER = logging.getLogger(__name__) -REGISTRATIONS_FILE = "html5_push_registrations.conf" +REGISTRATIONS_FILE = 'html5_push_registrations.conf' ATTR_GCM_SENDER_ID = 'gcm_sender_id' ATTR_GCM_API_KEY = 'gcm_api_key' @@ -43,11 +45,58 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ ATTR_SUBSCRIPTION = 'subscription' ATTR_BROWSER = 'browser' +ATTR_ENDPOINT = 'endpoint' +ATTR_KEYS = 'keys' +ATTR_AUTH = 'auth' +ATTR_P256DH = 'p256dh' + +ATTR_TAG = 'tag' +ATTR_ACTION = 'action' +ATTR_ACTIONS = 'actions' +ATTR_TYPE = 'type' +ATTR_URL = 'url' + +ATTR_JWT = 'jwt' + +# The number of days after the moment a notification is sent that a JWT +# is valid. +JWT_VALID_DAYS = 7 + +KEYS_SCHEMA = vol.All(dict, + vol.Schema({ + vol.Required(ATTR_AUTH): cv.string, + vol.Required(ATTR_P256DH): cv.string + })) + +SUBSCRIPTION_SCHEMA = vol.All(dict, + vol.Schema({ + # pylint: disable=no-value-for-parameter + vol.Required(ATTR_ENDPOINT): vol.Url(), + vol.Required(ATTR_KEYS): KEYS_SCHEMA + })) + REGISTER_SCHEMA = vol.Schema({ - vol.Required(ATTR_SUBSCRIPTION): cv.match_all, + vol.Required(ATTR_SUBSCRIPTION): SUBSCRIPTION_SCHEMA, vol.Required(ATTR_BROWSER): vol.In(['chrome', 'firefox']) }) +CALLBACK_EVENT_PAYLOAD_SCHEMA = vol.Schema({ + vol.Required(ATTR_TAG): cv.string, + vol.Required(ATTR_TYPE): vol.In(['received', 'clicked', 'closed']), + vol.Required(ATTR_TARGET): cv.string, + vol.Optional(ATTR_ACTION): cv.string, + vol.Optional(ATTR_DATA): dict, +}) + +NOTIFY_CALLBACK_EVENT = 'html5_notification' + +# badge and timestamp are Chrome specific (not in official spec) + +HTML5_SHOWNOTIFICATION_PARAMETERS = ('actions', 'badge', 'body', 'dir', + 'icon', 'lang', 'renotify', + 'requireInteraction', 'tag', 'timestamp', + 'vibrate') + def get_service(hass, config): """Get the HTML5 push notification service.""" @@ -60,12 +109,14 @@ def get_service(hass, config): hass.wsgi.register_view( HTML5PushRegistrationView(hass, registrations, json_path)) + hass.wsgi.register_view(HTML5PushCallbackView(hass, registrations)) - gcm_api_key = config.get('gcm_api_key') - gcm_sender_id = config.get('gcm_sender_id') + gcm_api_key = config.get(ATTR_GCM_API_KEY) + gcm_sender_id = config.get(ATTR_GCM_SENDER_ID) if gcm_sender_id is not None: - add_manifest_json_key('gcm_sender_id', config.get('gcm_sender_id')) + add_manifest_json_key(ATTR_GCM_SENDER_ID, + config.get(ATTR_GCM_SENDER_ID)) return HTML5NotificationService(gcm_api_key, registrations) @@ -76,7 +127,7 @@ def _load_config(filename): return {} try: - with open(filename, "r") as fdesc: + with open(filename, 'r') as fdesc: inp = fdesc.read() # In case empty file @@ -85,17 +136,17 @@ def _load_config(filename): return json.loads(inp) except (IOError, ValueError) as error: - _LOGGER.error("Reading config file %s failed: %s", filename, error) + _LOGGER.error('Reading config file %s failed: %s', filename, error) return None def _save_config(filename, config): """Save configuration.""" try: - with open(filename, "w") as fdesc: + with open(filename, 'w') as fdesc: fdesc.write(json.dumps(config, indent=4, sort_keys=True)) except (IOError, TypeError) as error: - _LOGGER.error("Saving config file failed: %s", error) + _LOGGER.error('Saving config file failed: %s', error) return False return True @@ -103,8 +154,8 @@ def _save_config(filename, config): class HTML5PushRegistrationView(HomeAssistantView): """Accepts push registrations from a browser.""" - url = "/api/notify.html5" - name = "api:notify.html5" + url = '/api/notify.html5' + name = 'api:notify.html5' def __init__(self, hass, registrations, json_path): """Init HTML5PushRegistrationView.""" @@ -129,7 +180,101 @@ class HTML5PushRegistrationView(HomeAssistantView): return self.json_message('Error saving registration.', HTTP_INTERNAL_SERVER_ERROR) - return self.json_message("Push notification subscriber registered.") + return self.json_message('Push notification subscriber registered.') + + +class HTML5PushCallbackView(HomeAssistantView): + """Accepts push registrations from a browser.""" + + requires_auth = False + url = '/api/notify.html5/callback' + name = 'api:notify.html5/callback' + + def __init__(self, hass, registrations): + """Init HTML5PushCallbackView.""" + super().__init__(hass) + self.registrations = registrations + + def decode_jwt(self, token): + """Find the registration that signed this JWT and return it.""" + import jwt + + # 1. Check claims w/o verifying to see if a target is in there. + # 2. If target in claims, attempt to verify against the given name. + # 2a. If decode is successful, return the payload. + # 2b. If decode is unsuccessful, return a 401. + + target_check = jwt.decode(token, verify=False) + if target_check[ATTR_TARGET] in self.registrations: + possible_target = self.registrations[target_check[ATTR_TARGET]] + key = possible_target[ATTR_SUBSCRIPTION][ATTR_KEYS][ATTR_AUTH] + try: + return jwt.decode(token, key) + except jwt.exceptions.DecodeError: + pass + + return self.json_message('No target found in JWT', + status_code=HTTP_UNAUTHORIZED) + + # The following is based on code from Auth0 + # https://auth0.com/docs/quickstart/backend/python + # pylint: disable=too-many-return-statements + def check_authorization_header(self, request): + """Check the authorization header.""" + import jwt + auth = request.headers.get('Authorization', None) + if not auth: + return self.json_message('Authorization header is expected', + status_code=HTTP_UNAUTHORIZED) + + parts = auth.split() + + if parts[0].lower() != 'bearer': + return self.json_message('Authorization header must ' + 'start with Bearer', + status_code=HTTP_UNAUTHORIZED) + elif len(parts) != 2: + return self.json_message('Authorization header must ' + 'be Bearer token', + status_code=HTTP_UNAUTHORIZED) + + token = parts[1] + try: + payload = self.decode_jwt(token) + except jwt.exceptions.InvalidTokenError: + return self.json_message('token is invalid', + status_code=HTTP_UNAUTHORIZED) + return payload + + def post(self, request): + """Accept the POST request for push registrations event callback.""" + auth_check = self.check_authorization_header(request) + if not isinstance(auth_check, dict): + return auth_check + + event_payload = { + ATTR_TAG: request.json.get(ATTR_TAG), + ATTR_TYPE: request.json[ATTR_TYPE], + ATTR_TARGET: auth_check[ATTR_TARGET], + } + + if request.json.get(ATTR_ACTION) is not None: + event_payload[ATTR_ACTION] = request.json.get(ATTR_ACTION) + + if request.json.get(ATTR_DATA) is not None: + event_payload[ATTR_DATA] = request.json.get(ATTR_DATA) + + try: + event_payload = CALLBACK_EVENT_PAYLOAD_SCHEMA(event_payload) + except vol.Invalid as ex: + _LOGGER.warning('Callback event payload is not valid! %s', + humanize_error(event_payload, ex)) + + event_name = '{}.{}'.format(NOTIFY_CALLBACK_EVENT, + event_payload[ATTR_TYPE]) + self.hass.bus.fire(event_name, event_payload) + return self.json({'status': 'ok', + 'event': event_payload[ATTR_TYPE]}) # pylint: disable=too-few-public-methods @@ -147,31 +292,41 @@ class HTML5NotificationService(BaseNotificationService): """Return a dictionary of registered targets.""" return self.registrations.keys() + # pylint: disable=too-many-locals def send_message(self, message="", **kwargs): """Send a message to a user.""" + import jwt from pywebpush import WebPusher timestamp = int(time.time()) + tag = str(uuid.uuid4()) payload = { - 'body': message, - 'data': {}, - 'icon': '/static/icons/favicon-192x192.png', 'badge': '/static/images/notification-badge.png', + 'body': message, + ATTR_DATA: {}, + 'icon': '/static/icons/favicon-192x192.png', + ATTR_TAG: tag, 'timestamp': (timestamp*1000), # Javascript ms since epoch - 'title': kwargs.get(ATTR_TITLE) + ATTR_TITLE: kwargs.get(ATTR_TITLE) } data = kwargs.get(ATTR_DATA) if data: - payload.update(data) + # Pick out fields that should go into the notification directly vs + # into the notification data dictionary. - if data.get('url') is not None: - payload['data']['url'] = data.get('url') - elif (payload['data'].get('url') is None and - payload.get('actions') is None): - payload['data']['url'] = '/' + for key, val in data.copy().items(): + if key in HTML5_SHOWNOTIFICATION_PARAMETERS: + payload[key] = val + del data[key] + + payload[ATTR_DATA] = data + + if (payload[ATTR_DATA].get(ATTR_URL) is None and + payload.get(ATTR_ACTIONS) is None): + payload[ATTR_DATA][ATTR_URL] = URL_ROOT targets = kwargs.get(ATTR_TARGET) @@ -183,9 +338,18 @@ class HTML5NotificationService(BaseNotificationService): for target in targets: info = self.registrations.get(target) if info is None: - _LOGGER.error("%s is not a valid HTML5 push notification" - " target!", target) + _LOGGER.error('%s is not a valid HTML5 push notification' + ' target!', target) continue + jwt_exp = (datetime.datetime.fromtimestamp(timestamp) + + datetime.timedelta(days=JWT_VALID_DAYS)) + jwt_secret = info[ATTR_SUBSCRIPTION][ATTR_KEYS][ATTR_AUTH] + jwt_claims = {'exp': jwt_exp, 'nbf': timestamp, + 'iat': timestamp, ATTR_TARGET: target, + ATTR_TAG: payload[ATTR_TAG]} + jwt_token = jwt.encode(jwt_claims, jwt_secret).decode('utf-8') + payload[ATTR_DATA][ATTR_JWT] = jwt_token + WebPusher(info[ATTR_SUBSCRIPTION]).send( json.dumps(payload), gcm_key=self._gcm_key, ttl='86400') diff --git a/requirements_all.txt b/requirements_all.txt index 4f0a4aa12e6..851fd2aa3c4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -10,6 +10,9 @@ typing>=3,<4 # homeassistant.components.isy994 PyISY==1.0.6 +# homeassistant.components.notify.html5 +PyJWT==1.4.2 + # homeassistant.components.arduino PyMata==2.12 diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py index 121cc1096d2..6201fb24ea0 100644 --- a/tests/components/notify/test_html5.py +++ b/tests/components/notify/test_html5.py @@ -42,7 +42,10 @@ class TestHtml5Notify(object): data = { 'device': { 'browser': 'chrome', - 'subscription': 'hello world', + 'subscription': { + 'endpoint': 'https://google.com', + 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} + }, } } @@ -60,7 +63,10 @@ class TestHtml5Notify(object): assert len(mock_wp.mock_calls) == 2 # WebPusher constructor - assert mock_wp.mock_calls[0][1][0] == 'hello world' + assert mock_wp.mock_calls[0][1][0] == {'endpoint': + 'https://google.com', + 'keys': {'auth': 'auth', + 'p256dh': 'p256dh'}} # Call to send payload = json.loads(mock_wp.mock_calls[1][1][0]) @@ -80,7 +86,7 @@ class TestHtml5Notify(object): assert service is not None # assert hass.called - assert len(hass.mock_calls) == 2 + assert len(hass.mock_calls) == 3 view = hass.mock_calls[1][1][0] assert view.json_path == fp.name @@ -88,7 +94,9 @@ class TestHtml5Notify(object): builder = EnvironBuilder(method='POST', data=json.dumps({ 'browser': 'chrome', - 'subscription': 'sub info', + 'subscription': {'endpoint': 'https://google.com', + 'keys': {'auth': 'auth', + 'p256dh': 'p256dh'}}, })) Request = request_class() resp = view.post(Request(builder.get_environ())) @@ -96,7 +104,9 @@ class TestHtml5Notify(object): expected = { 'unnamed device': { 'browser': 'chrome', - 'subscription': 'sub info', + 'subscription': {'endpoint': 'https://google.com', + 'keys': {'auth': 'auth', + 'p256dh': 'p256dh'}}, }, } @@ -116,7 +126,7 @@ class TestHtml5Notify(object): assert service is not None # assert hass.called - assert len(hass.mock_calls) == 2 + assert len(hass.mock_calls) == 3 view = hass.mock_calls[1][1][0] @@ -142,4 +152,89 @@ class TestHtml5Notify(object): with patch('homeassistant.components.notify.html5._save_config', return_value=False): resp = view.post(Request(builder.get_environ())) - assert resp.status_code == 500, resp.response + assert resp.status_code == 400, resp.response + + def test_callback_view_no_jwt(self): + """Test that the notification callback view works without JWT.""" + hass = MagicMock() + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + fp.close() + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + view = hass.mock_calls[2][1][0] + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'type': 'push', + 'tag': '3bc28d69-0921-41f1-ac6a-7a627ba0aa72' + })) + Request = request_class() + resp = view.post(Request(builder.get_environ())) + + assert resp.status_code == 401, resp.response + + @patch('pywebpush.WebPusher') + def test_callback_view_with_jwt(self, mock_wp): + """Test that the notification callback view works with JWT.""" + hass = MagicMock() + + data = { + 'device': { + 'browser': 'chrome', + 'subscription': { + 'endpoint': 'https://google.com', + 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} + }, + } + } + + with tempfile.NamedTemporaryFile() as fp: + fp.write(json.dumps(data).encode('utf-8')) + fp.flush() + hass.config.path.return_value = fp.name + service = html5.get_service(hass, {'gcm_sender_id': '100'}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + service.send_message('Hello', target=['device'], + data={'icon': 'beer.png'}) + + assert len(mock_wp.mock_calls) == 2 + + # WebPusher constructor + assert mock_wp.mock_calls[0][1][0] == {'endpoint': + 'https://google.com', + 'keys': {'auth': 'auth', + 'p256dh': + 'p256dh'}} + + # Call to send + push_payload = json.loads(mock_wp.mock_calls[1][1][0]) + + assert push_payload['body'] == 'Hello' + assert push_payload['icon'] == 'beer.png' + + view = hass.mock_calls[2][1][0] + view.registrations = data + + bearer_token = "Bearer {}".format(push_payload['data']['jwt']) + + builder = EnvironBuilder(method='POST', data=json.dumps({ + 'type': 'push', + }), headers={'Authorization': bearer_token}) + Request = request_class() + resp = view.post(Request(builder.get_environ())) + + assert resp.status_code == 200, resp.response + returned = resp.response[0].decode('utf-8') + expected = '{"event": "push", "status": "ok"}' + assert json.loads(returned) == json.loads(expected) From 98f236c75482ad0ae8de8c66659276f55dbdb50e Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 18 Aug 2016 09:39:37 +0300 Subject: [PATCH 068/193] Add webos customize option to add custom sources (#2561) Currently there are only hw inputs in the sources list. Other interesting inputs can be live tv (dvbt) and vod apps. * add customize option for webos * add short names for livetv, youtube, mako apps * add current app as a source * use large icon (largeIcon is the same as icon if doesn't exists) * filter out hw inputs that are not connected Signed-off-by: Roi Dayan --- .../components/media_player/webostv.py | 67 +++++++++++++------ 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/media_player/webostv.py b/homeassistant/components/media_player/webostv.py index 4d3bb701586..a0ba2237391 100644 --- a/homeassistant/components/media_player/webostv.py +++ b/homeassistant/components/media_player/webostv.py @@ -15,7 +15,8 @@ from homeassistant.components.media_player import ( SUPPORT_SELECT_SOURCE, SUPPORT_PLAY_MEDIA, MEDIA_TYPE_CHANNEL, MediaPlayerDevice) from homeassistant.const import ( - CONF_HOST, STATE_OFF, STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN) + CONF_HOST, CONF_CUSTOMIZE, STATE_OFF, STATE_PLAYING, STATE_PAUSED, + STATE_UNKNOWN) from homeassistant.loader import get_component _CONFIGURING = {} @@ -33,6 +34,16 @@ SUPPORT_WEBOSTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) +WEBOS_APP_LIVETV = 'com.webos.app.livetv' +WEBOS_APP_YOUTUBE = 'youtube.leanback.v4' +WEBOS_APP_MAKO = 'makotv' + +WEBOS_APPS_SHORT = { + 'livetv': WEBOS_APP_LIVETV, + 'youtube': WEBOS_APP_YOUTUBE, + 'makotv': WEBOS_APP_MAKO +} + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): @@ -50,10 +61,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if host in _CONFIGURING: return - setup_tv(host, hass, add_devices) + customize = config.get(CONF_CUSTOMIZE, {}) + setup_tv(host, customize, hass, add_devices) -def setup_tv(host, hass, add_devices): +def setup_tv(host, customize, hass, add_devices): """Setup a phue bridge based on host parameter.""" from pylgtv import WebOsClient from pylgtv import PyLGTVPairException @@ -75,7 +87,7 @@ def setup_tv(host, hass, add_devices): else: # Not registered, request configuration. _LOGGER.warning('LG WebOS TV at %s needs to be paired.', host) - request_configuration(host, hass, add_devices) + request_configuration(host, customize, hass, add_devices) return # If we came here and configuring this host, mark as done. @@ -84,10 +96,10 @@ def setup_tv(host, hass, add_devices): configurator = get_component('configurator') configurator.request_done(request_id) - add_devices([LgWebOSDevice(host)]) + add_devices([LgWebOSDevice(host, customize)]) -def request_configuration(host, hass, add_devices): +def request_configuration(host, customize, hass, add_devices): """Request configuration steps from the user.""" configurator = get_component('configurator') @@ -100,7 +112,7 @@ def request_configuration(host, hass, add_devices): # pylint: disable=unused-argument def lgtv_configuration_callback(data): """The actions to do when our configuration callback is called.""" - setup_tv(host, hass, add_devices) + setup_tv(host, customize, hass, add_devices) _CONFIGURING[host] = configurator.request_config( hass, 'LG WebOS TV', lgtv_configuration_callback, @@ -116,10 +128,11 @@ class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" # pylint: disable=too-many-public-methods - def __init__(self, host): + def __init__(self, host, customize): """Initialize the webos device.""" from pylgtv import WebOsClient self._client = WebOsClient(host) + self._customize = customize self._name = 'LG WebOS TV Remote' # Assume that the TV is not muted @@ -130,7 +143,6 @@ class LgWebOSDevice(MediaPlayerDevice): self._current_source = None self._current_source_id = None self._source_list = None - self._source_label_list = None self._state = STATE_UNKNOWN self._app_list = None @@ -144,19 +156,30 @@ class LgWebOSDevice(MediaPlayerDevice): self._muted = self._client.get_muted() self._volume = self._client.get_volume() self._current_source_id = self._client.get_input() - self._source_list = {} - self._source_label_list = [] self._app_list = {} + + custom_sources = [] + for source in self._customize.get('sources', []): + app_id = WEBOS_APPS_SHORT.get(source, None) + if app_id: + custom_sources.append(app_id) + else: + custom_sources.append(source) + for app in self._client.get_apps(): self._app_list[app['id']] = app + if app['id'] == self._current_source_id: + self._current_source = app['title'] + self._source_list[app['title']] = app + if app['id'] in custom_sources: + self._source_list[app['title']] = app for source in self._client.get_inputs(): - self._source_list[source['label']] = source - self._app_list[source['appId']] = source - self._source_label_list.append(source['label']) - if source['appId'] == self._current_source_id: - self._current_source = source['label'] + if not source['connected']: + continue + app = self._app_list[source['appId']] + self._source_list[app['title']] = app except OSError: self._state = STATE_OFF @@ -189,7 +212,7 @@ class LgWebOSDevice(MediaPlayerDevice): @property def source_list(self): """List of available input sources.""" - return self._source_label_list + return sorted(self._source_list.keys()) @property def media_content_type(self): @@ -199,7 +222,9 @@ class LgWebOSDevice(MediaPlayerDevice): @property def media_image_url(self): """Image url of current playing media.""" - return self._app_list[self._current_source_id]['icon'] + if self._current_source_id in self._app_list: + return self._app_list[self._current_source_id]['largeIcon'] + return None @property def supported_media_commands(self): @@ -238,9 +263,9 @@ class LgWebOSDevice(MediaPlayerDevice): def select_source(self, source): """Select input source.""" - self._current_source_id = self._source_list[source]['appId'] - self._current_source = self._source_list[source]['label'] - self._client.set_input(self._source_list[source]['id']) + self._current_source_id = self._source_list[source]['id'] + self._current_source = self._source_list[source]['title'] + self._client.launch_app(self._source_list[source]['id']) def media_play(self): """Send play command.""" From ccd8f5125331dd5231b5e69d70635bf57a142b72 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Thu, 18 Aug 2016 08:41:05 +0200 Subject: [PATCH 069/193] Ble tracker (#2810) * Added Bluetooth Low Energy device tracker * Added new file(s) * Fixed pylint errors * Remove traling zeros from device names * recreated deleted file * Added requirements * Renamed to bluetooth_le tracker Removed gattlib from tests Minor code cleanup * - fixed .coveragerc bug - changed discovery algorithm, new devices will only be added if seen 5 times to make sure HA doesn't blow the database with devices just passing by --- .coveragerc | 1 + .../device_tracker/bluetooth_le_tracker.py | 108 ++++++++++++++++++ requirements_all.txt | 3 + script/gen_requirements_all.py | 1 + 4 files changed, 113 insertions(+) create mode 100644 homeassistant/components/device_tracker/bluetooth_le_tracker.py diff --git a/.coveragerc b/.coveragerc index acb72210603..d686a035687 100644 --- a/.coveragerc +++ b/.coveragerc @@ -113,6 +113,7 @@ omit = homeassistant/components/device_tracker/aruba.py homeassistant/components/device_tracker/asuswrt.py homeassistant/components/device_tracker/bluetooth_tracker.py + homeassistant/components/device_tracker/bluetooth_le_tracker.py homeassistant/components/device_tracker/bt_home_hub_5.py homeassistant/components/device_tracker/ddwrt.py homeassistant/components/device_tracker/fritz.py diff --git a/homeassistant/components/device_tracker/bluetooth_le_tracker.py b/homeassistant/components/device_tracker/bluetooth_le_tracker.py new file mode 100644 index 00000000000..7784a2326d8 --- /dev/null +++ b/homeassistant/components/device_tracker/bluetooth_le_tracker.py @@ -0,0 +1,108 @@ +"""Tracking for bluetooth devices.""" +import logging +from datetime import timedelta + +from homeassistant.helpers.event import track_point_in_utc_time +from homeassistant.components.device_tracker import ( + YAML_DEVICES, + CONF_TRACK_NEW, + CONF_SCAN_INTERVAL, + DEFAULT_SCAN_INTERVAL, + load_config, +) +import homeassistant.util as util +import homeassistant.util.dt as dt_util + +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['gattlib==0.20150805'] + +BLE_PREFIX = 'BLE_' +MIN_SEEN_NEW = 5 + + +def setup_scanner(hass, config, see): + """Setup the Bluetooth LE Scanner.""" + # pylint: disable=import-error + from gattlib import DiscoveryService + + new_devices = {} + + def see_device(address, name, new_device=False): + """Mark a device as seen.""" + if new_device: + if address in new_devices: + _LOGGER.debug("Seen %s %s times", address, + new_devices[address]) + new_devices[address] += 1 + if new_devices[address] >= MIN_SEEN_NEW: + _LOGGER.debug("Adding %s to tracked devices", address) + devs_to_track.append(address) + else: + return + else: + _LOGGER.debug("Seen %s for the first time", address) + new_devices[address] = 1 + return + + see(mac=BLE_PREFIX + address, host_name=name.strip("\x00")) + + def discover_ble_devices(): + """Discover Bluetooth LE devices.""" + _LOGGER.debug("Discovering Bluetooth LE devices") + service = DiscoveryService() + devices = service.discover(10) + _LOGGER.debug("Bluetooth LE devices discovered = %s", devices) + + return devices + + yaml_path = hass.config.path(YAML_DEVICES) + devs_to_track = [] + devs_donot_track = [] + + # Load all known devices. + # We just need the devices so set consider_home and home range + # to 0 + for device in load_config(yaml_path, hass, 0, 0): + # check if device is a valid bluetooth device + if device.mac and device.mac[:3].upper() == BLE_PREFIX: + if device.track: + devs_to_track.append(device.mac[3:]) + else: + devs_donot_track.append(device.mac[3:]) + + # if track new devices is true discover new devices + # on every scan. + track_new = util.convert(config.get(CONF_TRACK_NEW), bool, + len(devs_to_track) == 0) + if not devs_to_track and not track_new: + _LOGGER.warning("No Bluetooth LE devices to track!") + return False + + interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, + DEFAULT_SCAN_INTERVAL) + + def update_ble(now): + """Lookup Bluetooth LE devices and update status.""" + devs = discover_ble_devices() + for mac in devs_to_track: + _LOGGER.debug("Checking " + mac) + result = mac in devs + if not result: + # Could not lookup device name + continue + see_device(mac, devs[mac]) + + if track_new: + for address in devs: + if address not in devs_to_track and \ + address not in devs_donot_track: + _LOGGER.info("Discovered Bluetooth LE device %s", address) + see_device(address, devs[address], new_device=True) + + track_point_in_utc_time(hass, update_ble, + now + timedelta(seconds=interval)) + + update_ble(dt_util.utcnow()) + + return True diff --git a/requirements_all.txt b/requirements_all.txt index 851fd2aa3c4..0a210e55b98 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -85,6 +85,9 @@ freesms==0.1.0 # homeassistant.components.conversation fuzzywuzzy==0.11.1 +# homeassistant.components.device_tracker.bluetooth_le_tracker +# gattlib==0.20150805 + # homeassistant.components.notify.gntp gntp==1.0.3 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 1fae3b92600..2ca7339e127 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -14,6 +14,7 @@ COMMENT_REQUIREMENTS = ( 'pybluez', 'bluepy', 'python-lirc', + 'gattlib' ) IGNORE_PACKAGES = ( From 053a55bc5f7491daad8c79c05f01fcefc0094ec8 Mon Sep 17 00:00:00 2001 From: Emil Horpen Hetty Date: Thu, 18 Aug 2016 08:54:08 +0200 Subject: [PATCH 070/193] Added name support for Forecast.io (#2638) * Added support for name Added name support and changed default name to "Forecast.io" since "Weather" had conflict with Yahoo weather and Open weather map * Update forecast.py --- homeassistant/components/sensor/forecast.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index 44fe4c2042a..0ab2301dbe2 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -55,6 +55,7 @@ SENSOR_TYPES = { 'precip_intensity_max': ['Daily Max Precip Intensity', 'mm', 'in', 'mm', 'mm', 'mm'], } +DEFAULT_NAME = "Forecast.io" # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) @@ -88,11 +89,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(error) return False + name = config.get('name', DEFAULT_NAME) + # Initialize and add all of the sensors. sensors = [] for variable in config['monitored_conditions']: if variable in SENSOR_TYPES: - sensors.append(ForeCastSensor(forecast_data, variable)) + sensors.append(ForeCastSensor(forecast_data, variable, name)) else: _LOGGER.error('Sensor type: "%s" does not exist', variable) @@ -103,9 +106,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ForeCastSensor(Entity): """Implementation of a Forecast.io sensor.""" - def __init__(self, forecast_data, sensor_type): + def __init__(self, forecast_data, sensor_type, name): """Initialize the sensor.""" - self.client_name = 'Weather' + self.client_name = name self._name = SENSOR_TYPES[sensor_type][0] self.forecast_data = forecast_data self.type = sensor_type From 09d531b3b95e7943df53233d1abcb40d7e87de94 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Thu, 18 Aug 2016 03:08:58 -0400 Subject: [PATCH 071/193] fix gpmdp (#2864) * fix gpmdp * fix balloobs comments * move create_connection --- .../components/media_player/gpmdp.py | 176 +++++++++++++++--- 1 file changed, 145 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py index eb6e15379d8..f6f649f3b63 100644 --- a/homeassistant/components/media_player/gpmdp.py +++ b/homeassistant/components/media_player/gpmdp.py @@ -6,6 +6,7 @@ https://home-assistant.io/components/media_player.gpmdp/ """ import logging import json +import os import socket from homeassistant.components.media_player import ( @@ -13,24 +14,132 @@ from homeassistant.components.media_player import ( SUPPORT_PAUSE, MediaPlayerDevice) from homeassistant.const import ( STATE_PLAYING, STATE_PAUSED, STATE_OFF) +from homeassistant.loader import get_component _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['websocket-client==0.37.0'] SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK +GPMDP_CONFIG_FILE = 'gpmpd.conf' +_CONFIGURING = {} -def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the GPMDP platform.""" +def request_configuration(hass, config, url, add_devices_callback): + """Request configuration steps from the user.""" + configurator = get_component('configurator') + if 'gpmdp' in _CONFIGURING: + configurator.notify_errors( + _CONFIGURING['gpmdp'], "Failed to register, please try again.") + + return from websocket import create_connection + websocket = create_connection((url), timeout=1) + websocket.send('{"namespace": "connect", "method": "connect",' + '"arguments": ["Home Assistant"]}') + # pylint: disable=unused-argument + def gpmdp_configuration_callback(callback_data): + """The actions to do when our configuration callback is called.""" + while True: + from websocket import _exceptions + try: + msg = json.loads(websocket.recv()) + except _exceptions.WebSocketConnectionClosedException: + continue + if msg['channel'] != 'connect': + continue + if msg['payload'] != "CODE_REQUIRED": + continue + websocket.send('{"namespace": "connect",' + '"method": "connect",' + '"arguments": ["Home Assistant",' + ' "' + callback_data.get('pin') + '"]}') + tmpmsg = json.loads(websocket.recv()) + if tmpmsg['channel'] == 'time': + _LOGGER.error('Error setting up GPMDP. Please pause' + 'the desktop player and try again.') + break + code = tmpmsg['payload'] + if code == 'CODE_REQUIRED': + continue + setup_gpmdp(hass, config, code, + add_devices_callback) + _save_config(hass.config.path(GPMDP_CONFIG_FILE), + {"CODE": code}) + websocket.send('{"namespace": "connect",' + '"method": "connect",' + '"arguments": ["Home Assistant",' + ' "' + code + '"]}') + websocket.close() + + _CONFIGURING['gpmdp'] = configurator.request_config( + hass, "GPM Desktop Player", gpmdp_configuration_callback, + description=( + 'Enter the pin that is displayed in the ' + 'Google Play Music Desktop Player.'), + submit_caption="Submit", + fields=[{'id': 'pin', 'name': 'Pin Code', 'type': 'number'}] + ) + + +def setup_gpmdp(hass, config, code, add_devices_callback): + """Setup gpmdp.""" name = config.get("name", "GPM Desktop Player") address = config.get("address") + url = "ws://" + address + ":5672" - if address is None: - _LOGGER.error("Missing address in config") + if not code: + request_configuration(hass, config, url, add_devices_callback) + return + + if 'gpmdp' in _CONFIGURING: + configurator = get_component('configurator') + configurator.request_done(_CONFIGURING.pop('gpmdp')) + + add_devices_callback([GPMDP(name, url, code)]) + + +def _load_config(filename): + """Load configuration.""" + if not os.path.isfile(filename): + return {} + + try: + with open(filename, "r") as fdesc: + inp = fdesc.read() + + # In case empty file + if not inp: + return {} + + return json.loads(inp) + except (IOError, ValueError) as error: + _LOGGER.error("Reading config file %s failed: %s", filename, error) + return None + + +def _save_config(filename, config): + """Save configuration.""" + try: + with open(filename, "w") as fdesc: + fdesc.write(json.dumps(config, indent=4, sort_keys=True)) + except (IOError, TypeError) as error: + _LOGGER.error("Saving config file failed: %s", error) return False + return True - add_devices([GPMDP(name, address, create_connection)]) + +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup the GPMDP platform.""" + codeconfig = _load_config(hass.config.path(GPMDP_CONFIG_FILE)) + if len(codeconfig): + code = codeconfig.get("CODE") + elif discovery_info is not None: + if 'gpmdp' in _CONFIGURING: + return + code = None + else: + code = None + setup_gpmdp(hass, config, code, add_devices_callback) class GPMDP(MediaPlayerDevice): @@ -38,10 +147,12 @@ class GPMDP(MediaPlayerDevice): # pylint: disable=too-many-public-methods, abstract-method # pylint: disable=too-many-instance-attributes - def __init__(self, name, address, create_connection): + def __init__(self, name, url, code): """Initialize the media player.""" + from websocket import create_connection self._connection = create_connection - self._address = address + self._url = url + self._authorization_code = code self._name = name self._status = STATE_OFF self._ws = None @@ -54,16 +165,12 @@ class GPMDP(MediaPlayerDevice): """Check if the websocket is setup and connected.""" if self._ws is None: try: - self._ws = self._connection(("ws://" + self._address + - ":5672"), timeout=1) - except (socket.timeout, ConnectionRefusedError, - ConnectionResetError): - self._ws = None - elif self._ws.connected is True: - self._ws.close() - try: - self._ws = self._connection(("ws://" + self._address + - ":5672"), timeout=1) + self._ws = self._connection((self._url), timeout=1) + msg = json.dumps({'namespace': 'connect', + 'method': 'connect', + 'arguments': ['Home Assistant', + self._authorization_code]}) + self._ws.send(msg) except (socket.timeout, ConnectionRefusedError, ConnectionResetError): self._ws = None @@ -76,19 +183,26 @@ class GPMDP(MediaPlayerDevice): self._status = STATE_OFF return else: - state = websocket.recv() - state = ((json.loads(state))['payload']) - if state is True: - websocket.recv() - websocket.recv() - song = websocket.recv() - song = json.loads(song) - self._title = (song['payload']['title']) - self._artist = (song['payload']['artist']) - self._albumart = (song['payload']['albumArt']) - self._status = STATE_PLAYING - elif state is False: - self._status = STATE_PAUSED + receiving = True + while receiving: + from websocket import _exceptions + try: + msg = json.loads(websocket.recv()) + if msg['channel'] == 'lyrics': + receiving = False # end of now playing data + elif msg['channel'] == 'playState': + if msg['payload'] is True: + self._status = STATE_PLAYING + else: + self._status = STATE_PAUSED + elif msg['channel'] == 'track': + self._title = (msg['payload']['title']) + self._artist = (msg['payload']['artist']) + self._albumart = (msg['payload']['albumArt']) + except (_exceptions.WebSocketTimeoutException, + _exceptions.WebSocketProtocolException, + _exceptions.WebSocketPayloadException): + return @property def media_content_type(self): @@ -145,7 +259,7 @@ class GPMDP(MediaPlayerDevice): if websocket is None: return websocket.send('{"namespace": "playback", "method": "playPause"}') - self._status = STATE_PAUSED + self._status = STATE_PLAYING self.update_ha_state() def media_pause(self): From 90fdc8983840d403e43ddd2018a93f4a55d89152 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Thu, 18 Aug 2016 09:59:41 -0400 Subject: [PATCH 072/193] Updated to address @balloob's comments --- homeassistant/components/sensor/wunderground.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 979bff40a89..e727b5d79a8 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -13,9 +13,7 @@ from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, STATE_UNKNOWN) CONF_PWS_ID = 'pws_id' - -_URL_QUERY = '/conditions/q/' -_RESOURCE = 'http://api.wunderground.com/api/' +_RESOURCE = 'http://api.wunderground.com/api/{}/conditions/q/' _LOGGER = logging.getLogger(__name__) # Return cached results if last scan was less then this time ago. @@ -56,14 +54,13 @@ PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): "wunderground", vol.Required(CONF_API_KEY): vol.Coerce(str), CONF_PWS_ID: vol.Coerce(str), - vol.Required(CONF_MONITORED_CONDITIONS, default=[]): ensure_list, + vol.Required(CONF_MONITORED_CONDITIONS, + default=[]): vol.All(ensure_list, [vol.In(SENSOR_TYPES)]), }) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" - if not PLATFORM_SCHEMA(config): - return False rest = WUndergroundData(hass, config.get(CONF_API_KEY), @@ -139,8 +136,7 @@ class WUndergroundData(object): self.data = None def _build_url(self): - print(self._api_key) - url = _RESOURCE + self._api_key + _URL_QUERY + url = _RESOURCE.format(self._api_key) if self._pws_id: url = url + 'pws:' + self._pws_id else: From 230dde4b5777d5ac6ecab2766cc89793f43fdcd8 Mon Sep 17 00:00:00 2001 From: arsaboo Date: Thu, 18 Aug 2016 10:12:56 -0400 Subject: [PATCH 073/193] Removed blank line (linting error) --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index e727b5d79a8..cb724247436 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -61,7 +61,6 @@ PLATFORM_SCHEMA = vol.Schema({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Wunderground sensor.""" - rest = WUndergroundData(hass, config.get(CONF_API_KEY), config.get(CONF_PWS_ID, None)) From 41f84d9e204386722a7bab676addcf6d0dd35937 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:27:38 -0600 Subject: [PATCH 074/193] Pydoc for unit test methods --- tests/components/sensor/test_wunderground.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index c6664b71254..6c4979fb440 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -28,12 +28,17 @@ ICON_URL = 'http://icons.wxug.com/i/c/k/clear.gif' def mocked_requests_get(*args, **kwargs): + """Mock requests.get invocations.""" + class MockResponse: + """Class to represent a mocked response.""" def __init__(self, json_data, status_code): + """Initialize the mock response class.""" self.json_data = json_data self.status_code = status_code def json(self): + """Return the json of the response.""" return self.json_data if str(args[0]).startswith('http://api.wunderground.com/api/foo/'): @@ -123,6 +128,7 @@ class TestWundergroundSetup(unittest.TestCase): @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) def test_sensor(self, req_mock): + """Test the wundergroun sensor class and methods.""" wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, None) print(str(self.DEVICES)) From 2b8e2a3d36c671e7ce562e0b46257f0009bdf142 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:27:53 -0600 Subject: [PATCH 075/193] Remove print lines --- tests/components/sensor/test_wunderground.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index 6c4979fb440..15a903aec56 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -42,8 +42,6 @@ def mocked_requests_get(*args, **kwargs): return self.json_data if str(args[0]).startswith('http://api.wunderground.com/api/foo/'): - # Return valid response - print('VALID RESPONSE') return MockResponse({ "response": { "version": "0.1", @@ -65,8 +63,6 @@ def mocked_requests_get(*args, **kwargs): } }, 200) else: - # Return invalid api key - print('INVALID RESPONSE') return MockResponse({ "response": { "version": "0.1", @@ -104,11 +100,9 @@ class TestWundergroundSetup(unittest.TestCase): @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) def test_setup(self, req_mock): """Test that the component is loaded if passed in PSW Id.""" - print('1') self.assertTrue( wunderground.setup_platform(self.hass, VALID_CONFIG_PWS, self.add_devices, None)) - print('2') self.assertTrue( wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, @@ -131,7 +125,6 @@ class TestWundergroundSetup(unittest.TestCase): """Test the wundergroun sensor class and methods.""" wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, None) - print(str(self.DEVICES)) for device in self.DEVICES: self.assertTrue(str(device.name).startswith('PWS_')) if device.name == 'PWS_weather': From 0490fe832a34d84c9980c24e267b8bb9d839dd4a Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:32:19 -0600 Subject: [PATCH 076/193] Unneeded validation removed --- homeassistant/components/sensor/wunderground.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index cb724247436..509a1e91ffa 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -66,10 +66,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get(CONF_PWS_ID, None)) sensors = [] for variable in config['monitored_conditions']: - if variable in SENSOR_TYPES: - sensors.append(WUndergroundSensor(rest, variable)) - else: - _LOGGER.error('Wunderground sensor: "%s" does not exist', variable) + sensors.append(WUndergroundSensor(rest, variable)) try: rest.update() From 6f57d36134e3b3b7c7e50b56be62edb88f32cb6f Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:37:00 -0600 Subject: [PATCH 077/193] Add doc link to header of file --- homeassistant/components/sensor/wunderground.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 509a1e91ffa..21ebcd1107b 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -1,4 +1,9 @@ -"""Support for Wunderground weather service.""" +""" +Support for Weather Underground weather service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.wunderground/ +""" from datetime import timedelta import logging import requests From ddec28da4b342f14c928ee6fbbb2d0765e24944f Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:37:26 -0600 Subject: [PATCH 078/193] Use schema validators already avaialble --- homeassistant/components/sensor/wunderground.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 21ebcd1107b..7e45d115eb6 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -11,7 +11,7 @@ import requests import voluptuous as vol from homeassistant.helpers.entity import Entity -from homeassistant.helpers.config_validation import ensure_list +from homeassistant.helpers.config_validation import (ensure_list, string) from homeassistant.util import Throttle from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, @@ -57,8 +57,8 @@ SENSOR_TYPES = { PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): "wunderground", - vol.Required(CONF_API_KEY): vol.Coerce(str), - CONF_PWS_ID: vol.Coerce(str), + vol.Required(CONF_API_KEY): string, + vol.Optional(CONF_PWS_ID): string, vol.Required(CONF_MONITORED_CONDITIONS, default=[]): vol.All(ensure_list, [vol.In(SENSOR_TYPES)]), }) From db2d9ec854713c8277cb6ff48c17aef3bf9ad775 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:37:39 -0600 Subject: [PATCH 079/193] Unused property --- homeassistant/components/sensor/wunderground.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 7e45d115eb6..737133e5c1d 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -91,7 +91,6 @@ class WUndergroundSensor(Entity): """Initialize the sensor.""" self.rest = rest self._condition = condition - self._unit_of_measurement = None @property def name(self): From ec5e20f0d99e2c7a7022073ad4516028ca10135e Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:38:34 -0600 Subject: [PATCH 080/193] Use string constant --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 737133e5c1d..c041d7ceaff 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -70,7 +70,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get(CONF_API_KEY), config.get(CONF_PWS_ID, None)) sensors = [] - for variable in config['monitored_conditions']: + for variable in config[CONF_MONITORED_CONDITIONS]: sensors.append(WUndergroundSensor(rest, variable)) try: From c2b75140bf01b8c8e57a4a835f7cae017b15a939 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:40:28 -0600 Subject: [PATCH 081/193] Fix config validation import to make things more readable --- homeassistant/components/sensor/wunderground.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index c041d7ceaff..7d3084b47be 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -11,7 +11,7 @@ import requests import voluptuous as vol from homeassistant.helpers.entity import Entity -from homeassistant.helpers.config_validation import (ensure_list, string) +import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, @@ -57,10 +57,10 @@ SENSOR_TYPES = { PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): "wunderground", - vol.Required(CONF_API_KEY): string, - vol.Optional(CONF_PWS_ID): string, + vol.Required(CONF_API_KEY): cv.string, + vol.Optional(CONF_PWS_ID): cv.string, vol.Required(CONF_MONITORED_CONDITIONS, - default=[]): vol.All(ensure_list, [vol.In(SENSOR_TYPES)]), + default=[]): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), }) From 25840f97c258423a0c4d2dbdaa6aa7947e56d502 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:46:04 -0600 Subject: [PATCH 082/193] Consistent use of WUnderground --- homeassistant/components/sensor/wunderground.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 7d3084b47be..00e5fdb3e1d 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -1,5 +1,5 @@ """ -Support for Weather Underground weather service. +Support for WUnderground weather service. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.wunderground/ @@ -65,7 +65,7 @@ PLATFORM_SCHEMA = vol.Schema({ def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Wunderground sensor.""" + """Setup the WUnderground sensor.""" rest = WUndergroundData(hass, config.get(CONF_API_KEY), config.get(CONF_PWS_ID, None)) @@ -85,7 +85,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class WUndergroundSensor(Entity): - """Implementing the Wunderground sensor.""" + """Implementing the WUnderground sensor.""" def __init__(self, rest, condition): """Initialize the sensor.""" @@ -124,7 +124,7 @@ class WUndergroundSensor(Entity): class WUndergroundData(object): - """Get data from Wundeground.""" + """Get data from WUnderground.""" def __init__(self, hass, api_key, pws_id=None): """Initialize the data object.""" @@ -146,7 +146,7 @@ class WUndergroundData(object): @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): - """Get the latest data from wunderground.""" + """Get the latest data from WUnderground.""" try: result = requests.get(self._build_url(), timeout=10).json() if "error" in result['response']: @@ -155,6 +155,6 @@ class WUndergroundData(object): else: self.data = result["current_observation"] except ValueError as err: - _LOGGER.error("Check Wunderground API %s", err.args) + _LOGGER.error("Check WUnderground API %s", err.args) self.data = None raise From 90449a90f1360f580b0a9d476c6d99cd1f182290 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:46:24 -0600 Subject: [PATCH 083/193] Use string templating --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 00e5fdb3e1d..e4fa30cabe3 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -138,7 +138,7 @@ class WUndergroundData(object): def _build_url(self): url = _RESOURCE.format(self._api_key) if self._pws_id: - url = url + 'pws:' + self._pws_id + url = url + 'pws:{}'.format(self._pws_id) else: url = url + '{},{}'.format(self._latitude, self._longitude) From 5bdcf60a214b84dbd9e81ea5b8d9db5c29deed11 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Thu, 18 Aug 2016 10:47:52 -0600 Subject: [PATCH 084/193] Extend platform schema --- homeassistant/components/sensor/wunderground.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index e4fa30cabe3..16672b03b4b 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, STATE_UNKNOWN) @@ -55,7 +56,7 @@ SENSOR_TYPES = { 'solarradiation': ['Solar Radiation', None] } -PLATFORM_SCHEMA = vol.Schema({ +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_PLATFORM): "wunderground", vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_PWS_ID): cv.string, From df4a9ea1da5638089830b3ed13473d2d8263f0cf Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 18 Aug 2016 23:14:14 +0200 Subject: [PATCH 085/193] add move_postion support for HA rollershutter / CONFIG_SCHEMA (#2873) --- homeassistant/components/homematic.py | 74 ++++++++++++------- .../components/rollershutter/homematic.py | 4 +- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index 1a917789638..8568408f3ec 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -12,7 +12,7 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN, - CONF_USERNAME, CONF_PASSWORD) + CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM) from homeassistant.helpers.entity import Entity from homeassistant.helpers import discovery from homeassistant.config import load_yaml_config_file @@ -67,7 +67,8 @@ HM_ATTRIBUTE_SUPPORT = { 'CONTROL_MODE': ['Mode', {0: 'Auto', 1: 'Manual', 2: 'Away', 3: 'Boost'}], 'POWER': ['Power', {}], 'CURRENT': ['Current', {}], - 'VOLTAGE': ['Voltage', {}] + 'VOLTAGE': ['Voltage', {}], + 'WORKING': ['Working', {0: 'No', 1: 'Yes'}], } HM_PRESS_EVENTS = [ @@ -97,18 +98,29 @@ CONF_REMOTE_PORT = 'remote_port' CONF_RESOLVENAMES = 'resolvenames' CONF_DELAY = 'delay' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_LOCAL_IP): cv.string, - vol.Optional(CONF_LOCAL_PORT, default=8943): cv.port, - vol.Required(CONF_REMOTE_IP): cv.string, - vol.Optional(CONF_REMOTE_PORT, default=2001): cv.port, - vol.Optional(CONF_RESOLVENAMES, default=False): - vol.In(CONF_RESOLVENAMES_OPTIONS), - vol.Optional(CONF_USERNAME, default="Admin"): cv.string, - vol.Optional(CONF_PASSWORD, default=""): cv.string, - vol.Optional(CONF_DELAY, default=0.5): cv.string, + +DEVICE_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): "homematic", + vol.Required(ATTR_NAME): cv.string, + vol.Required(ATTR_ADDRESS): cv.string, + vol.Optional(ATTR_CHANNEL, default=1): vol.Coerce(int), + vol.Optional(ATTR_PARAM): cv.string, }) +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_LOCAL_IP): cv.string, + vol.Optional(CONF_LOCAL_PORT, default=8943): cv.port, + vol.Required(CONF_REMOTE_IP): cv.string, + vol.Optional(CONF_REMOTE_PORT, default=2001): cv.port, + vol.Optional(CONF_RESOLVENAMES, default=False): + vol.In(CONF_RESOLVENAMES_OPTIONS), + vol.Optional(CONF_USERNAME, default="Admin"): cv.string, + vol.Optional(CONF_PASSWORD, default=""): cv.string, + vol.Optional(CONF_DELAY, default=0.5): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({ vol.Required(ATTR_ADDRESS): cv.string, vol.Required(ATTR_CHANNEL): vol.Coerce(int), @@ -123,14 +135,14 @@ def setup(hass, config): from pyhomematic import HMConnection - local_ip = config[DOMAIN][0].get(CONF_LOCAL_IP) - local_port = config[DOMAIN][0].get(CONF_LOCAL_PORT) - remote_ip = config[DOMAIN][0].get(CONF_REMOTE_IP) - remote_port = config[DOMAIN][0].get(CONF_REMOTE_PORT) - resolvenames = config[DOMAIN][0].get(CONF_RESOLVENAMES) - username = config[DOMAIN][0].get(CONF_USERNAME) - password = config[DOMAIN][0].get(CONF_PASSWORD) - HOMEMATIC_LINK_DELAY = config[DOMAIN][0].get(CONF_DELAY) + local_ip = config[DOMAIN].get(CONF_LOCAL_IP) + local_port = config[DOMAIN].get(CONF_LOCAL_PORT) + remote_ip = config[DOMAIN].get(CONF_REMOTE_IP) + remote_port = config[DOMAIN].get(CONF_REMOTE_PORT) + resolvenames = config[DOMAIN].get(CONF_RESOLVENAMES) + username = config[DOMAIN].get(CONF_USERNAME) + password = config[DOMAIN].get(CONF_PASSWORD) + HOMEMATIC_LINK_DELAY = config[DOMAIN].get(CONF_DELAY) if remote_ip is None or local_ip is None: _LOGGER.error("Missing remote CCU/Homegear or local address") @@ -217,8 +229,9 @@ def system_callback_handler(hass, config, src, *args): def _get_devices(device_type, keys): """Get the Homematic devices.""" - # run device_arr = [] + + # pylint: disable=too-many-nested-blocks for key in keys: device = HOMEMATIC.devices[key] class_name = device.__class__.__name__ @@ -244,15 +257,22 @@ def _get_devices(device_type, keys): name = _create_ha_name(name=device.NAME, channel=channel, param=param) - device_dict = dict(platform="homematic", - address=key, - name=name, - channel=channel) + device_dict = { + CONF_PLATFORM: "homematic", + ATTR_ADDRESS: key, + ATTR_NAME: name, + ATTR_CHANNEL: channel + } if param is not None: - device_dict[ATTR_PARAM] = param + device_dict.update({ATTR_PARAM: param}) # Add new device - device_arr.append(device_dict) + try: + DEVICE_SCHEMA(device_dict) + device_arr.append(device_dict) + except vol.MultipleInvalid as err: + _LOGGER.error("Invalid device config: %s", + str(err)) else: _LOGGER.debug("Channel %i not in params", channel) else: diff --git a/homeassistant/components/rollershutter/homematic.py b/homeassistant/components/rollershutter/homematic.py index 805c5dceb82..613d7884919 100644 --- a/homeassistant/components/rollershutter/homematic.py +++ b/homeassistant/components/rollershutter/homematic.py @@ -45,8 +45,8 @@ class HMRollershutter(homematic.HMDevice, RollershutterDevice): return int((1 - self._hm_get_state()) * 100) return None - def position(self, **kwargs): - """Move to a defined position: 0 (closed) and 100 (open).""" + def move_position(self, **kwargs): + """Move the roller shutter to a specific position.""" if self.available: if ATTR_CURRENT_POSITION in kwargs: position = float(kwargs[ATTR_CURRENT_POSITION]) From cb3a37691f92104bbc0adc61c2972877a913275b Mon Sep 17 00:00:00 2001 From: Teagan Glenn Date: Thu, 18 Aug 2016 16:28:19 -0600 Subject: [PATCH 086/193] Type-o --- tests/components/sensor/test_wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index 15a903aec56..fccbbf3ca6c 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -122,7 +122,7 @@ class TestWundergroundSetup(unittest.TestCase): @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) def test_sensor(self, req_mock): - """Test the wundergroun sensor class and methods.""" + """Test the wunderground sensor class and methods.""" wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, None) for device in self.DEVICES: From 297fca93512c2548638523f476e52d8ff8f83ea8 Mon Sep 17 00:00:00 2001 From: Teagan Glenn Date: Thu, 18 Aug 2016 16:39:16 -0600 Subject: [PATCH 087/193] Type-o --- tests/components/sensor/test_wunderground.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index fccbbf3ca6c..2de7da580f9 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -1,4 +1,4 @@ -"""The tests for the forecast.io platform.""" +"""The tests for the WUnderground platform.""" import unittest from homeassistant.components.sensor import wunderground @@ -78,7 +78,7 @@ def mocked_requests_get(*args, **kwargs): class TestWundergroundSetup(unittest.TestCase): - """Test the wunderground platform.""" + """Test the WUnderground platform.""" DEVICES = [] @@ -99,7 +99,7 @@ class TestWundergroundSetup(unittest.TestCase): @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) def test_setup(self, req_mock): - """Test that the component is loaded if passed in PSW Id.""" + """Test that the component is loaded if passed in PWS Id.""" self.assertTrue( wunderground.setup_platform(self.hass, VALID_CONFIG_PWS, self.add_devices, None)) @@ -122,7 +122,7 @@ class TestWundergroundSetup(unittest.TestCase): @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) def test_sensor(self, req_mock): - """Test the wunderground sensor class and methods.""" + """Test the WUnderground sensor class and methods.""" wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, None) for device in self.DEVICES: From 9bfac590f6cb4652b9e4518459408c84564f5f4b Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Thu, 18 Aug 2016 19:21:01 -0400 Subject: [PATCH 088/193] fix 2862 (#2868) --- homeassistant/components/sensor/plex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/plex.py b/homeassistant/components/sensor/plex.py index 4ef01304488..62d60ff695f 100644 --- a/homeassistant/components/sensor/plex.py +++ b/homeassistant/components/sensor/plex.py @@ -96,7 +96,7 @@ class PlexSensor(Entity): sessions = self._server.sessions() now_playing = [] for sess in sessions: - user = sess.user.title if sess.user is not self._na_type else "" + user = sess.username if sess.username is not self._na_type else "" title = sess.title if sess.title is not self._na_type else "" year = sess.year if sess.year is not self._na_type else "" now_playing.append((user, "{0} ({1})".format(title, year))) From bafc9413a333fdc7c3c9ca2ae4eb2ebfbfdbd069 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 18 Aug 2016 22:45:42 -0700 Subject: [PATCH 089/193] Fix media player art (#2879) --- homeassistant/components/media_player/__init__.py | 1 + tests/components/media_player/test_demo.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 7efbbe01653..38e476c5d8c 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -667,6 +667,7 @@ class MediaPlayerDevice(Entity): class MediaPlayerImageView(HomeAssistantView): """Media player view to serve an image.""" + requires_auth = False url = "/api/media_player_proxy/" name = "api:media_player:image" diff --git a/tests/components/media_player/test_demo.py b/tests/components/media_player/test_demo.py index f2b9ce4b032..03a97a44b30 100644 --- a/tests/components/media_player/test_demo.py +++ b/tests/components/media_player/test_demo.py @@ -2,6 +2,7 @@ import unittest from unittest.mock import patch from homeassistant import bootstrap +from homeassistant.const import HTTP_HEADER_HA_AUTH import homeassistant.components.media_player as mp import homeassistant.components.http as http @@ -13,6 +14,8 @@ from tests.common import get_test_home_assistant, get_test_instance_port SERVER_PORT = get_test_instance_port() HTTP_BASE_URL = 'http://127.0.0.1:{}'.format(SERVER_PORT) +API_PASSWORD = "test1234" +HA_HEADERS = {HTTP_HEADER_HA_AUTH: API_PASSWORD} hass = None @@ -26,7 +29,8 @@ def setUpModule(): # pylint: disable=invalid-name hass = get_test_home_assistant() bootstrap.setup_component(hass, http.DOMAIN, { http.DOMAIN: { - http.CONF_SERVER_PORT: SERVER_PORT + http.CONF_SERVER_PORT: SERVER_PORT, + http.CONF_API_PASSWORD: API_PASSWORD, }, }) From 2a563e1604cf52b2efd8908e9e483b430a84bbce Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Fri, 19 Aug 2016 03:11:56 -0400 Subject: [PATCH 090/193] binary occupancy sensor (#2869) --- .../components/binary_sensor/ecobee.py | 72 +++++++++++++++++++ homeassistant/components/ecobee.py | 1 + homeassistant/components/sensor/ecobee.py | 9 +-- 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 homeassistant/components/binary_sensor/ecobee.py diff --git a/homeassistant/components/binary_sensor/ecobee.py b/homeassistant/components/binary_sensor/ecobee.py new file mode 100644 index 00000000000..09cbfd852e3 --- /dev/null +++ b/homeassistant/components/binary_sensor/ecobee.py @@ -0,0 +1,72 @@ +""" +Support for Ecobee sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.ecobee/ +""" +from homeassistant.components import ecobee +from homeassistant.components.binary_sensor import BinarySensorDevice + +DEPENDENCIES = ['ecobee'] + +ECOBEE_CONFIG_FILE = 'ecobee.conf' + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Ecobee sensors.""" + if discovery_info is None: + return + data = ecobee.NETWORK + dev = list() + for index in range(len(data.ecobee.thermostats)): + for sensor in data.ecobee.get_remote_sensors(index): + for item in sensor['capability']: + if item['type'] != 'occupancy': + continue + + dev.append(EcobeeBinarySensor(sensor['name'], index)) + + add_devices(dev) + + +class EcobeeBinarySensor(BinarySensorDevice): + """Representation of an Ecobee sensor.""" + + def __init__(self, sensor_name, sensor_index): + """Initialize the sensor.""" + self._name = sensor_name + ' Occupancy' + self.sensor_name = sensor_name + self.index = sensor_index + self._state = None + self._sensor_class = 'motion' + self.update() + + @property + def name(self): + """Return the name of the Ecobee sensor.""" + return self._name.rstrip() + + @property + def is_on(self): + """Return the status of the sensor.""" + return self._state == 'true' + + @property + def unique_id(self): + """Return the unique ID of this sensor.""" + return "binary_sensor_ecobee_{}_{}".format(self._name, self.index) + + @property + def sensor_class(self): + """Return the class of this sensor, from SENSOR_CLASSES.""" + return self._sensor_class + + def update(self): + """Get the latest state of the sensor.""" + data = ecobee.NETWORK + data.update() + for sensor in data.ecobee.get_remote_sensors(self.index): + for item in sensor['capability']: + if (item['type'] == 'occupancy' and + self.sensor_name == sensor['name']): + self._state = item['value'] diff --git a/homeassistant/components/ecobee.py b/homeassistant/components/ecobee.py index 48d689364ee..470449b02cb 100644 --- a/homeassistant/components/ecobee.py +++ b/homeassistant/components/ecobee.py @@ -72,6 +72,7 @@ def setup_ecobee(hass, network, config): discovery.load_platform(hass, 'thermostat', DOMAIN, {'hold_temp': hold_temp}, config) discovery.load_platform(hass, 'sensor', DOMAIN, {}, config) + discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config) # pylint: disable=too-few-public-methods diff --git a/homeassistant/components/sensor/ecobee.py b/homeassistant/components/sensor/ecobee.py index 61ce2b6770c..961fb9aabe3 100644 --- a/homeassistant/components/sensor/ecobee.py +++ b/homeassistant/components/sensor/ecobee.py @@ -4,8 +4,6 @@ Support for Ecobee sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.ecobee/ """ -import logging - from homeassistant.components import ecobee from homeassistant.const import TEMP_FAHRENHEIT from homeassistant.helpers.entity import Entity @@ -13,11 +11,9 @@ from homeassistant.helpers.entity import Entity DEPENDENCIES = ['ecobee'] SENSOR_TYPES = { 'temperature': ['Temperature', TEMP_FAHRENHEIT], - 'humidity': ['Humidity', '%'], - 'occupancy': ['Occupancy', None] + 'humidity': ['Humidity', '%'] } -_LOGGER = logging.getLogger(__name__) ECOBEE_CONFIG_FILE = 'ecobee.conf' @@ -30,8 +26,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for index in range(len(data.ecobee.thermostats)): for sensor in data.ecobee.get_remote_sensors(index): for item in sensor['capability']: - if item['type'] not in ('temperature', - 'humidity', 'occupancy'): + if item['type'] not in ('temperature', 'humidity'): continue dev.append(EcobeeSensor(sensor['name'], item['type'], index)) From 0abc50e84458c9ed490c61a74dcce9c4085ae7f1 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 19 Aug 2016 09:12:56 +0200 Subject: [PATCH 091/193] Use voluptuous for transport sensors (#2867) --- .../components/sensor/deutsche_bahn.py | 9 ++-- .../components/sensor/google_travel_time.py | 53 ++++++++++--------- .../sensor/swiss_public_transport.py | 31 +++++++---- 3 files changed, 53 insertions(+), 40 deletions(-) diff --git a/homeassistant/components/sensor/deutsche_bahn.py b/homeassistant/components/sensor/deutsche_bahn.py index 2dc589271e9..b358a4b975a 100644 --- a/homeassistant/components/sensor/deutsche_bahn.py +++ b/homeassistant/components/sensor/deutsche_bahn.py @@ -9,7 +9,7 @@ from datetime import timedelta import voluptuous as vol -from homeassistant.const import (CONF_PLATFORM) +from homeassistant.components.sensor import PLATFORM_SCHEMA import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle from homeassistant.helpers.entity import Entity @@ -23,10 +23,9 @@ ICON = 'mdi:train' _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'deutsche_bahn', - vol.Required(CONF_START): cv.string, +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_DESTINATION): cv.string, + vol.Required(CONF_START): cv.string, }) # Return cached results if last scan was less then this time ago. @@ -47,7 +46,7 @@ class DeutscheBahnSensor(Entity): def __init__(self, start, goal): """Initialize the sensor.""" - self._name = start + ' to ' + goal + self._name = '{} to {}'.format(start, goal) self.data = SchieneData(start, goal) self.update() diff --git a/homeassistant/components/sensor/google_travel_time.py b/homeassistant/components/sensor/google_travel_time.py index 378e9c9c124..d95f43d68ae 100644 --- a/homeassistant/components/sensor/google_travel_time.py +++ b/homeassistant/components/sensor/google_travel_time.py @@ -7,12 +7,14 @@ https://home-assistant.io/components/sensor.google_travel_time/ from datetime import datetime from datetime import timedelta import logging + import voluptuous as vol +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity from homeassistant.const import ( - CONF_API_KEY, EVENT_HOMEASSISTANT_START, ATTR_LATITUDE, ATTR_LONGITUDE) - + CONF_API_KEY, CONF_NAME, EVENT_HOMEASSISTANT_START, ATTR_LATITUDE, + ATTR_LONGITUDE) from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv import homeassistant.helpers.location as location @@ -25,12 +27,12 @@ REQUIREMENTS = ['googlemaps==2.4.4'] # Return cached results if last update was less then this time ago MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5) +DEFAULT_NAME = 'Google Travel Time' CONF_ORIGIN = 'origin' CONF_DESTINATION = 'destination' CONF_TRAVEL_MODE = 'travel_mode' CONF_OPTIONS = 'options' CONF_MODE = 'mode' -CONF_NAME = 'name' ALL_LANGUAGES = ['ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'eu', 'fa', 'fi', 'fr', 'gl', 'gu', 'hi', 'hr', 'hu', 'id', @@ -40,35 +42,33 @@ ALL_LANGUAGES = ['ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'zh-CN', 'zh-TW'] TRANSIT_PREFS = ['less_walking', 'fewer_transfers'] +TRAVEL_MODE = ['driving', 'walking', 'bicycling', 'transit'] +AVOID = ['tolls', 'highways', 'ferries', 'indoor'] +TRANSPORT_TYPE = ['bus', 'subway', 'train', 'tram', 'rail'] +TRAVEL_MODEL = ['best_guess', 'pessimistic', 'optimistic'] +UNITS = ['metric', 'imperial'] -PLATFORM_SCHEMA = vol.Schema({ - vol.Required('platform'): 'google_travel_time', - vol.Optional(CONF_NAME): vol.Coerce(str), - vol.Required(CONF_API_KEY): vol.Coerce(str), - vol.Required(CONF_ORIGIN): vol.Coerce(str), - vol.Required(CONF_DESTINATION): vol.Coerce(str), - vol.Optional(CONF_TRAVEL_MODE): - vol.In(["driving", "walking", "bicycling", "transit"]), +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_DESTINATION): cv.string, + vol.Required(CONF_ORIGIN): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_TRAVEL_MODE): vol.In(TRAVEL_MODE), vol.Optional(CONF_OPTIONS, default={CONF_MODE: 'driving'}): vol.All( dict, vol.Schema({ - vol.Optional(CONF_MODE, default='driving'): - vol.In(["driving", "walking", "bicycling", "transit"]), + vol.Optional(CONF_MODE, default='driving'): vol.In(TRAVEL_MODE), vol.Optional('language'): vol.In(ALL_LANGUAGES), - vol.Optional('avoid'): vol.In(['tolls', 'highways', - 'ferries', 'indoor']), - vol.Optional('units'): vol.In(['metric', 'imperial']), + vol.Optional('avoid'): vol.In(AVOID), + vol.Optional('units'): vol.In(UNITS), vol.Exclusive('arrival_time', 'time'): cv.string, vol.Exclusive('departure_time', 'time'): cv.string, - vol.Optional('traffic_model'): vol.In(['best_guess', - 'pessimistic', - 'optimistic']), - vol.Optional('transit_mode'): vol.In(['bus', 'subway', 'train', - 'tram', 'rail']), + vol.Optional('traffic_model'): vol.In(TRAVEL_MODEL), + vol.Optional('transit_mode'): vol.In(TRANSPORT_TYPE), vol.Optional('transit_routing_preference'): vol.In(TRANSIT_PREFS) })) }) -TRACKABLE_DOMAINS = ["device_tracker", "sensor", "zone"] +TRACKABLE_DOMAINS = ['device_tracker', 'sensor', 'zone'] def convert_time_to_utc(timestr): @@ -81,10 +81,10 @@ def convert_time_to_utc(timestr): def setup_platform(hass, config, add_devices_callback, discovery_info=None): - """Setup the travel time platform.""" + """Setup the Google travel time platform.""" # pylint: disable=too-many-locals def run_setup(event): - """Delay the setup until home assistant is fully initialized. + """Delay the setup until Home Assistant is fully initialized. This allows any entities to be created already """ @@ -122,7 +122,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): # pylint: disable=too-many-instance-attributes class GoogleTravelTimeSensor(Entity): - """Representation of a tavel time sensor.""" + """Representation of a Google travel time sensor.""" # pylint: disable=too-many-arguments def __init__(self, hass, name, api_key, origin, destination, options): @@ -130,6 +130,7 @@ class GoogleTravelTimeSensor(Entity): self._hass = hass self._name = name self._options = options + self._unit_of_measurement = 'min' self._matrix = None self.valid_api_connection = True @@ -192,7 +193,7 @@ class GoogleTravelTimeSensor(Entity): @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" - return "min" + return self._unit_of_measurement @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): diff --git a/homeassistant/components/sensor/swiss_public_transport.py b/homeassistant/components/sensor/swiss_public_transport.py index 2ca1992659b..0bfdc286bb6 100644 --- a/homeassistant/components/sensor/swiss_public_transport.py +++ b/homeassistant/components/sensor/swiss_public_transport.py @@ -8,34 +8,49 @@ import logging from datetime import timedelta import requests +import voluptuous as vol +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME import homeassistant.util.dt as dt_util from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv -_LOGGER = logging.getLogger(__name__) _RESOURCE = 'http://transport.opendata.ch/v1/' +DEFAULT_NAME = 'Next Departure' ATTR_DEPARTURE_TIME1 = 'Next departure' ATTR_DEPARTURE_TIME2 = 'Next on departure' ATTR_START = 'Start' ATTR_TARGET = 'Destination' ATTR_REMAINING_TIME = 'Remaining time' +CONF_START = 'from' +CONF_DESTINATION = 'to' ICON = 'mdi:bus' TIME_STR_FORMAT = "%H:%M" +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DESTINATION): cv.string, + vol.Required(CONF_START): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) + # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) def setup_platform(hass, config, add_devices, discovery_info=None): """Get the Swiss public transport sensor.""" + name = config.get(CONF_NAME) # journal contains [0] Station ID start, [1] Station ID destination # [2] Station name start, and [3] Station name destination - journey = [config.get('from'), config.get('to')] + journey = [config.get(CONF_START), config.get(CONF_DESTINATION)] try: - for location in [config.get('from', None), config.get('to', None)]: + for location in [config.get(CONF_START), config.get(CONF_DESTINATION)]: # transport.opendata.ch doesn't play nice with requests.Session result = requests.get(_RESOURCE + 'locations?query=%s' % location, timeout=10) @@ -46,20 +61,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): "Check your settings and/or the availability of opendata.ch") return False - dev = [] data = PublicTransportData(journey) - dev.append(SwissPublicTransportSensor(data, journey)) - add_devices(dev) + add_devices([SwissPublicTransportSensor(data, journey, name)]) # pylint: disable=too-few-public-methods class SwissPublicTransportSensor(Entity): """Implementation of an Swiss public transport sensor.""" - def __init__(self, data, journey): + def __init__(self, data, journey, name): """Initialize the sensor.""" self.data = data - self._name = 'Next Departure' + self._name = name self._from = journey[2] self._to = journey[3] self.update() @@ -123,7 +136,7 @@ class PublicTransportData(object): 'to=' + self.destination + '&' + 'fields[]=connections/from/departureTimestamp/&' + 'fields[]=connections/', - timeout=30) + timeout=10) connections = response.json()['connections'][:2] try: From ada4de3ffb0476fc5f20a85bac3958637ec33552 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Fri, 19 Aug 2016 09:17:28 +0200 Subject: [PATCH 092/193] Migrate Thermostat and HVAC component to climate component (#2825) * First draft for climate * Updates for thermostats --- .coveragerc | 6 + homeassistant/components/climate/__init__.py | 535 ++++++++++++++++++ homeassistant/components/climate/demo.py | 164 ++++++ homeassistant/components/climate/ecobee.py | 247 ++++++++ .../components/climate/eq3btsmart.py | 90 +++ .../components/climate/generic_thermostat.py | 216 +++++++ homeassistant/components/climate/heatmiser.py | 114 ++++ homeassistant/components/climate/homematic.py | 90 +++ homeassistant/components/climate/honeywell.py | 266 +++++++++ homeassistant/components/climate/knx.py | 83 +++ homeassistant/components/climate/nest.py | 189 +++++++ homeassistant/components/climate/proliphix.py | 90 +++ .../components/climate/radiotherm.py | 136 +++++ .../components/climate/services.yaml | 84 +++ homeassistant/components/climate/zwave.py | 253 +++++++++ homeassistant/components/ecobee.py | 2 +- homeassistant/components/homematic.py | 4 +- homeassistant/components/nest.py | 2 +- homeassistant/components/thermostat/zwave.py | 4 + homeassistant/components/zwave.py | 20 +- requirements_all.txt | 6 + tests/components/climate/__init__.py | 1 + tests/components/climate/test_demo.py | 166 ++++++ .../climate/test_generic_thermostat.py | 493 ++++++++++++++++ tests/components/climate/test_honeywell.py | 377 ++++++++++++ 25 files changed, 3621 insertions(+), 17 deletions(-) create mode 100644 homeassistant/components/climate/__init__.py create mode 100644 homeassistant/components/climate/demo.py create mode 100644 homeassistant/components/climate/ecobee.py create mode 100644 homeassistant/components/climate/eq3btsmart.py create mode 100644 homeassistant/components/climate/generic_thermostat.py create mode 100644 homeassistant/components/climate/heatmiser.py create mode 100644 homeassistant/components/climate/homematic.py create mode 100644 homeassistant/components/climate/honeywell.py create mode 100644 homeassistant/components/climate/knx.py create mode 100644 homeassistant/components/climate/nest.py create mode 100644 homeassistant/components/climate/proliphix.py create mode 100644 homeassistant/components/climate/radiotherm.py create mode 100644 homeassistant/components/climate/services.yaml create mode 100755 homeassistant/components/climate/zwave.py create mode 100644 tests/components/climate/__init__.py create mode 100644 tests/components/climate/test_demo.py create mode 100644 tests/components/climate/test_generic_thermostat.py create mode 100644 tests/components/climate/test_honeywell.py diff --git a/.coveragerc b/.coveragerc index d686a035687..f68872401c2 100644 --- a/.coveragerc +++ b/.coveragerc @@ -109,6 +109,12 @@ omit = homeassistant/components/camera/generic.py homeassistant/components/camera/mjpeg.py homeassistant/components/camera/rpi_camera.py + homeassistant/components/climate/eq3btsmart.py + homeassistant/components/climate/heatmiser.py + homeassistant/components/climate/homematic.py + homeassistant/components/climate/knx.py + homeassistant/components/climate/proliphix.py + homeassistant/components/climate/radiotherm.py homeassistant/components/device_tracker/actiontec.py homeassistant/components/device_tracker/aruba.py homeassistant/components/device_tracker/asuswrt.py diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py new file mode 100644 index 00000000000..6ed289b2008 --- /dev/null +++ b/homeassistant/components/climate/__init__.py @@ -0,0 +1,535 @@ +""" +Provides functionality to interact with climate devices. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/climate/ +""" +import logging +import os +from numbers import Number +import voluptuous as vol + +from homeassistant.helpers.entity_component import EntityComponent + +from homeassistant.config import load_yaml_config_file +import homeassistant.util as util +from homeassistant.util.temperature import convert as convert_temperature +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa +import homeassistant.helpers.config_validation as cv +from homeassistant.const import ( + ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN, + TEMP_CELSIUS) + +DOMAIN = "climate" + +ENTITY_ID_FORMAT = DOMAIN + ".{}" +SCAN_INTERVAL = 60 + +SERVICE_SET_AWAY_MODE = "set_away_mode" +SERVICE_SET_AUX_HEAT = "set_aux_heat" +SERVICE_SET_TEMPERATURE = "set_temperature" +SERVICE_SET_FAN_MODE = "set_fan_mode" +SERVICE_SET_OPERATION_MODE = "set_operation_mode" +SERVICE_SET_SWING_MODE = "set_swing_mode" +SERVICE_SET_HUMIDITY = "set_humidity" + +STATE_HEAT = "heat" +STATE_COOL = "cool" +STATE_IDLE = "idle" +STATE_AUTO = "auto" +STATE_DRY = "dry" +STATE_FAN_ONLY = "fan_only" + +ATTR_CURRENT_TEMPERATURE = "current_temperature" +ATTR_MAX_TEMP = "max_temp" +ATTR_MIN_TEMP = "min_temp" +ATTR_AWAY_MODE = "away_mode" +ATTR_AUX_HEAT = "aux_heat" +ATTR_FAN_MODE = "fan_mode" +ATTR_FAN_LIST = "fan_list" +ATTR_CURRENT_HUMIDITY = "current_humidity" +ATTR_HUMIDITY = "humidity" +ATTR_MAX_HUMIDITY = "max_humidity" +ATTR_MIN_HUMIDITY = "min_humidity" +ATTR_OPERATION_MODE = "operation_mode" +ATTR_OPERATION_LIST = "operation_list" +ATTR_SWING_MODE = "swing_mode" +ATTR_SWING_LIST = "swing_list" + +_LOGGER = logging.getLogger(__name__) + +SET_AWAY_MODE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_AWAY_MODE): cv.boolean, +}) +SET_AUX_HEAT_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_AUX_HEAT): cv.boolean, +}) +SET_TEMPERATURE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_TEMPERATURE): vol.Coerce(float), +}) +SET_FAN_MODE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_FAN_MODE): cv.string, +}) +SET_OPERATION_MODE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_OPERATION_MODE): cv.string, +}) +SET_HUMIDITY_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_HUMIDITY): vol.Coerce(float), +}) +SET_SWING_MODE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_SWING_MODE): cv.string, +}) + + +def set_away_mode(hass, away_mode, entity_id=None): + """Turn all or specified climate devices away mode on.""" + data = { + ATTR_AWAY_MODE: away_mode + } + + if entity_id: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data) + + +def set_aux_heat(hass, aux_heat, entity_id=None): + """Turn all or specified climate devices auxillary heater on.""" + data = { + ATTR_AUX_HEAT: aux_heat + } + + if entity_id: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_AUX_HEAT, data) + + +def set_temperature(hass, temperature, entity_id=None): + """Set new target temperature.""" + data = {ATTR_TEMPERATURE: temperature} + + if entity_id is not None: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data) + + +def set_humidity(hass, humidity, entity_id=None): + """Set new target humidity.""" + data = {ATTR_HUMIDITY: humidity} + + if entity_id is not None: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_HUMIDITY, data) + + +def set_fan_mode(hass, fan, entity_id=None): + """Set all or specified climate devices fan mode on.""" + data = {ATTR_FAN_MODE: fan} + + if entity_id: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data) + + +def set_operation_mode(hass, operation_mode, entity_id=None): + """Set new target operation mode.""" + data = {ATTR_OPERATION_MODE: operation_mode} + + if entity_id is not None: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_OPERATION_MODE, data) + + +def set_swing_mode(hass, swing_mode, entity_id=None): + """Set new target swing mode.""" + data = {ATTR_SWING_MODE: swing_mode} + + if entity_id is not None: + data[ATTR_ENTITY_ID] = entity_id + + hass.services.call(DOMAIN, SERVICE_SET_SWING_MODE, data) + + +# pylint: disable=too-many-branches +def setup(hass, config): + """Setup climate devices.""" + component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) + component.setup(config) + + descriptions = load_yaml_config_file( + os.path.join(os.path.dirname(__file__), 'services.yaml')) + + def away_mode_set_service(service): + """Set away mode on target climate devices.""" + target_climate = component.extract_from_service(service) + + away_mode = service.data.get(ATTR_AWAY_MODE) + + if away_mode is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE) + return + + for climate in target_climate: + if away_mode: + climate.turn_away_mode_on() + else: + climate.turn_away_mode_off() + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_AWAY_MODE, away_mode_set_service, + descriptions.get(SERVICE_SET_AWAY_MODE), + schema=SET_AWAY_MODE_SCHEMA) + + def aux_heat_set_service(service): + """Set auxillary heater on target climate devices.""" + target_climate = component.extract_from_service(service) + + aux_heat = service.data.get(ATTR_AUX_HEAT) + + if aux_heat is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_AUX_HEAT, ATTR_AUX_HEAT) + return + + for climate in target_climate: + if aux_heat: + climate.turn_aux_heat_on() + else: + climate.turn_aux_heat_off() + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_AUX_HEAT, aux_heat_set_service, + descriptions.get(SERVICE_SET_AUX_HEAT), + schema=SET_AUX_HEAT_SCHEMA) + + def temperature_set_service(service): + """Set temperature on the target climate devices.""" + target_climate = component.extract_from_service(service) + + temperature = util.convert( + service.data.get(ATTR_TEMPERATURE), float) + + if temperature is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_TEMPERATURE, ATTR_TEMPERATURE) + return + + for climate in target_climate: + climate.set_temperature(convert_temperature( + temperature, hass.config.units.temperature_unit, + climate.unit_of_measurement)) + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service, + descriptions.get(SERVICE_SET_TEMPERATURE), + schema=SET_TEMPERATURE_SCHEMA) + + def humidity_set_service(service): + """Set humidity on the target climate devices.""" + target_climate = component.extract_from_service(service) + + humidity = service.data.get(ATTR_HUMIDITY) + + if humidity is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_HUMIDITY, ATTR_HUMIDITY) + return + + for climate in target_climate: + climate.set_humidity(humidity) + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_HUMIDITY, humidity_set_service, + descriptions.get(SERVICE_SET_HUMIDITY), + schema=SET_HUMIDITY_SCHEMA) + + def fan_mode_set_service(service): + """Set fan mode on target climate devices.""" + target_climate = component.extract_from_service(service) + + fan = service.data.get(ATTR_FAN_MODE) + + if fan is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_FAN_MODE, ATTR_FAN_MODE) + return + + for climate in target_climate: + climate.set_fan_mode(fan) + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_FAN_MODE, fan_mode_set_service, + descriptions.get(SERVICE_SET_FAN_MODE), + schema=SET_FAN_MODE_SCHEMA) + + def operation_set_service(service): + """Set operating mode on the target climate devices.""" + target_climate = component.extract_from_service(service) + + operation_mode = service.data.get(ATTR_OPERATION_MODE) + + if operation_mode is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_OPERATION_MODE, ATTR_OPERATION_MODE) + return + + for climate in target_climate: + climate.set_operation_mode(operation_mode) + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_OPERATION_MODE, operation_set_service, + descriptions.get(SERVICE_SET_OPERATION_MODE), + schema=SET_OPERATION_MODE_SCHEMA) + + def swing_set_service(service): + """Set swing mode on the target climate devices.""" + target_climate = component.extract_from_service(service) + + swing_mode = service.data.get(ATTR_SWING_MODE) + + if swing_mode is None: + _LOGGER.error( + "Received call to %s without attribute %s", + SERVICE_SET_SWING_MODE, ATTR_SWING_MODE) + return + + for climate in target_climate: + climate.set_swing_mode(swing_mode) + + if climate.should_poll: + climate.update_ha_state(True) + + hass.services.register( + DOMAIN, SERVICE_SET_SWING_MODE, swing_set_service, + descriptions.get(SERVICE_SET_SWING_MODE), + schema=SET_SWING_MODE_SCHEMA) + return True + + +class ClimateDevice(Entity): + """Representation of a climate device.""" + + # pylint: disable=too-many-public-methods,no-self-use + @property + def state(self): + """Return the current state.""" + return self.current_operation or STATE_UNKNOWN + + @property + def state_attributes(self): + """Return the optional state attributes.""" + data = { + ATTR_CURRENT_TEMPERATURE: + self._convert_for_display(self.current_temperature), + ATTR_MIN_TEMP: self._convert_for_display(self.min_temp), + ATTR_MAX_TEMP: self._convert_for_display(self.max_temp), + ATTR_TEMPERATURE: + self._convert_for_display(self.target_temperature), + } + + humidity = self.target_humidity + if humidity is not None: + data[ATTR_HUMIDITY] = humidity + data[ATTR_CURRENT_HUMIDITY] = self.current_humidity + data[ATTR_MIN_HUMIDITY] = self.min_humidity + data[ATTR_MAX_HUMIDITY] = self.max_humidity + + fan_mode = self.current_fan_mode + if fan_mode is not None: + data[ATTR_FAN_MODE] = fan_mode + data[ATTR_FAN_LIST] = self.fan_list + + operation_mode = self.current_operation + if operation_mode is not None: + data[ATTR_OPERATION_MODE] = operation_mode + data[ATTR_OPERATION_LIST] = self.operation_list + + swing_mode = self.current_swing_mode + if swing_mode is not None: + data[ATTR_SWING_MODE] = swing_mode + data[ATTR_SWING_LIST] = self.swing_list + + is_away = self.is_away_mode_on + if is_away is not None: + data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF + + is_aux_heat = self.is_aux_heat_on + if is_aux_heat is not None: + data[ATTR_AUX_HEAT] = STATE_ON if is_aux_heat else STATE_OFF + + return data + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + raise NotImplementedError + + @property + def current_humidity(self): + """Return the current humidity.""" + return None + + @property + def target_humidity(self): + """Return the humidity we try to reach.""" + return None + + @property + def current_operation(self): + """Return current operation ie. heat, cool, idle.""" + return None + + @property + def operation_list(self): + """List of available operation modes.""" + return None + + @property + def current_temperature(self): + """Return the current temperature.""" + return None + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return None + + @property + def is_away_mode_on(self): + """Return true if away mode is on.""" + return None + + @property + def is_aux_heat_on(self): + """Return true if aux heater.""" + return None + + @property + def current_fan_mode(self): + """Return the fan setting.""" + return None + + @property + def fan_list(self): + """List of available fan modes.""" + return None + + @property + def current_swing_mode(self): + """Return the fan setting.""" + return None + + @property + def swing_list(self): + """List of available swing modes.""" + return None + + def set_temperature(self, temperature): + """Set new target temperature.""" + raise NotImplementedError() + + def set_humidity(self, humidity): + """Set new target humidity.""" + raise NotImplementedError() + + def set_fan_mode(self, fan): + """Set new target fan mode.""" + raise NotImplementedError() + + def set_operation_mode(self, operation_mode): + """Set new target operation mode.""" + raise NotImplementedError() + + def set_swing_mode(self, swing_mode): + """Set new target swing operation.""" + raise NotImplementedError() + + def turn_away_mode_on(self): + """Turn away mode on.""" + raise NotImplementedError() + + def turn_away_mode_off(self): + """Turn away mode off.""" + raise NotImplementedError() + + def turn_aux_heat_on(self): + """Turn auxillary heater on.""" + raise NotImplementedError() + + def turn_aux_heat_off(self): + """Turn auxillary heater off.""" + raise NotImplementedError() + + @property + def min_temp(self): + """Return the minimum temperature.""" + return convert_temperature(7, TEMP_CELSIUS, self.unit_of_measurement) + + @property + def max_temp(self): + """Return the maximum temperature.""" + return convert_temperature(35, TEMP_CELSIUS, self.unit_of_measurement) + + @property + def min_humidity(self): + """Return the minimum humidity.""" + return 30 + + @property + def max_humidity(self): + """Return the maximum humidity.""" + return 99 + + def _convert_for_display(self, temp): + """Convert temperature into preferred units for display purposes.""" + if temp is None or not isinstance(temp, Number): + return temp + + value = convert_temperature(temp, self.unit_of_measurement, + self.hass.config.units.temperature_unit) + + if self.hass.config.units.temperature_unit is TEMP_CELSIUS: + decimal_count = 1 + else: + # Users of fahrenheit generally expect integer units. + decimal_count = 0 + + return round(value, decimal_count) diff --git a/homeassistant/components/climate/demo.py b/homeassistant/components/climate/demo.py new file mode 100644 index 00000000000..445a568d2f0 --- /dev/null +++ b/homeassistant/components/climate/demo.py @@ -0,0 +1,164 @@ +""" +Demo platform that offers a fake climate device. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/demo/ +""" +from homeassistant.components.climate import ClimateDevice +from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Demo climate devices.""" + add_devices([ + DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, 77, "Auto Low", + None, None, "Auto", "Heat", None), + DemoClimate("Hvac", 21, TEMP_CELSIUS, True, 22, "On High", + 67, 54, "Off", "Cool", False), + ]) + + +# pylint: disable=too-many-arguments, too-many-public-methods +class DemoClimate(ClimateDevice): + """Representation of a demo climate device.""" + + # pylint: disable=too-many-instance-attributes + def __init__(self, name, target_temperature, unit_of_measurement, + away, current_temperature, current_fan_mode, + target_humidity, current_humidity, current_swing_mode, + current_operation, aux): + """Initialize the climate device.""" + self._name = name + self._target_temperature = target_temperature + self._target_humidity = target_humidity + self._unit_of_measurement = unit_of_measurement + self._away = away + self._current_temperature = current_temperature + self._current_humidity = current_humidity + self._current_fan_mode = current_fan_mode + self._current_operation = current_operation + self._aux = aux + self._current_swing_mode = current_swing_mode + self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"] + self._operation_list = ["Heat", "Cool", "Auto Changeover", "Off"] + self._swing_list = ["Auto", 1, 2, 3, "Off"] + + @property + def should_poll(self): + """Polling not needed for a demo climate device.""" + return False + + @property + def name(self): + """Return the name of the climate device.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return self._unit_of_measurement + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temperature + + @property + def current_humidity(self): + """Return the current humidity.""" + return self._current_humidity + + @property + def target_humidity(self): + """Return the humidity we try to reach.""" + return self._target_humidity + + @property + def current_operation(self): + """Return current operation ie. heat, cool, idle.""" + return self._current_operation + + @property + def operation_list(self): + """List of available operation modes.""" + return self._operation_list + + @property + def is_away_mode_on(self): + """Return if away mode is on.""" + return self._away + + @property + def is_aux_heat_on(self): + """Return true if away mode is on.""" + return self._aux + + @property + def current_fan_mode(self): + """Return the fan setting.""" + return self._current_fan_mode + + @property + def fan_list(self): + """List of available fan modes.""" + return self._fan_list + + def set_temperature(self, temperature): + """Set new target temperature.""" + self._target_temperature = temperature + self.update_ha_state() + + def set_humidity(self, humidity): + """Set new target temperature.""" + self._target_humidity = humidity + self.update_ha_state() + + def set_swing_mode(self, swing_mode): + """Set new target temperature.""" + self._current_swing_mode = swing_mode + self.update_ha_state() + + def set_fan_mode(self, fan): + """Set new target temperature.""" + self._current_fan_mode = fan + self.update_ha_state() + + def set_operation_mode(self, operation_mode): + """Set new target temperature.""" + self._current_operation = operation_mode + self.update_ha_state() + + @property + def current_swing_mode(self): + """Return the swing setting.""" + return self._current_swing_mode + + @property + def swing_list(self): + """List of available swing modes.""" + return self._swing_list + + def turn_away_mode_on(self): + """Turn away mode on.""" + self._away = True + self.update_ha_state() + + def turn_away_mode_off(self): + """Turn away mode off.""" + self._away = False + self.update_ha_state() + + def turn_aux_heat_on(self): + """Turn away auxillary heater on.""" + self._aux = True + self.update_ha_state() + + def turn_aux_heat_off(self): + """Turn auxillary heater off.""" + self._aux = False + self.update_ha_state() diff --git a/homeassistant/components/climate/ecobee.py b/homeassistant/components/climate/ecobee.py new file mode 100644 index 00000000000..76038085385 --- /dev/null +++ b/homeassistant/components/climate/ecobee.py @@ -0,0 +1,247 @@ +""" +Platform for Ecobee Thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.ecobee/ +""" +import logging +from os import path +import voluptuous as vol + +from homeassistant.components import ecobee +from homeassistant.components.climate import ( + DOMAIN, STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice) +from homeassistant.const import ( + ATTR_ENTITY_ID, STATE_OFF, STATE_ON, TEMP_FAHRENHEIT) +from homeassistant.config import load_yaml_config_file +import homeassistant.helpers.config_validation as cv + +DEPENDENCIES = ['ecobee'] +_LOGGER = logging.getLogger(__name__) +ECOBEE_CONFIG_FILE = 'ecobee.conf' +_CONFIGURING = {} + +ATTR_FAN_MIN_ON_TIME = "fan_min_on_time" +SERVICE_SET_FAN_MIN_ON_TIME = "ecobee_set_fan_min_on_time" +SET_FAN_MIN_ON_TIME_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_FAN_MIN_ON_TIME): vol.Coerce(int), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Ecobee Thermostat Platform.""" + if discovery_info is None: + return + data = ecobee.NETWORK + hold_temp = discovery_info['hold_temp'] + _LOGGER.info( + "Loading ecobee thermostat component with hold_temp set to %s", + hold_temp) + devices = [Thermostat(data, index, hold_temp) + for index in range(len(data.ecobee.thermostats))] + add_devices(devices) + + def fan_min_on_time_set_service(service): + """Set the minimum fan on time on the target thermostats.""" + entity_id = service.data.get('entity_id') + + if entity_id: + target_thermostats = [device for device in devices + if device.entity_id == entity_id] + else: + target_thermostats = devices + + fan_min_on_time = service.data[ATTR_FAN_MIN_ON_TIME] + + for thermostat in target_thermostats: + thermostat.set_fan_min_on_time(str(fan_min_on_time)) + + thermostat.update_ha_state(True) + + descriptions = load_yaml_config_file( + path.join(path.dirname(__file__), 'services.yaml')) + + hass.services.register( + DOMAIN, SERVICE_SET_FAN_MIN_ON_TIME, fan_min_on_time_set_service, + descriptions.get(SERVICE_SET_FAN_MIN_ON_TIME), + schema=SET_FAN_MIN_ON_TIME_SCHEMA) + + +# pylint: disable=too-many-public-methods, abstract-method +class Thermostat(ClimateDevice): + """A thermostat class for Ecobee.""" + + def __init__(self, data, thermostat_index, hold_temp): + """Initialize the thermostat.""" + self.data = data + self.thermostat_index = thermostat_index + self.thermostat = self.data.ecobee.get_thermostat( + self.thermostat_index) + self._name = self.thermostat['name'] + self.hold_temp = hold_temp + + def update(self): + """Get the latest state from the thermostat.""" + self.data.update() + self.thermostat = self.data.ecobee.get_thermostat( + self.thermostat_index) + + @property + def name(self): + """Return the name of the Ecobee Thermostat.""" + return self.thermostat['name'] + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return TEMP_FAHRENHEIT + + @property + def current_temperature(self): + """Return the current temperature.""" + return self.thermostat['runtime']['actualTemperature'] / 10 + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + if (self.operation_mode == 'heat' or + self.operation_mode == 'auxHeatOnly'): + return self.target_temperature_low + elif self.operation_mode == 'cool': + return self.target_temperature_high + else: + return (self.target_temperature_low + + self.target_temperature_high) / 2 + + @property + def target_temperature_low(self): + """Return the lower bound temperature we try to reach.""" + return int(self.thermostat['runtime']['desiredHeat'] / 10) + + @property + def target_temperature_high(self): + """Return the upper bound temperature we try to reach.""" + return int(self.thermostat['runtime']['desiredCool'] / 10) + + @property + def current_humidity(self): + """Return the current humidity.""" + return self.thermostat['runtime']['actualHumidity'] + + @property + def desired_fan_mode(self): + """Return the desired fan mode of operation.""" + return self.thermostat['runtime']['desiredFanMode'] + + @property + def fan(self): + """Return the current fan state.""" + if 'fan' in self.thermostat['equipmentStatus']: + return STATE_ON + else: + return STATE_OFF + + @property + def operation_mode(self): + """Return current operation ie. heat, cool, idle.""" + status = self.thermostat['equipmentStatus'] + if status == '': + return STATE_IDLE + elif 'Cool' in status: + return STATE_COOL + elif 'auxHeat' in status: + return STATE_HEAT + elif 'heatPump' in status: + return STATE_HEAT + else: + return status + + @property + def mode(self): + """Return current mode ie. home, away, sleep.""" + return self.thermostat['program']['currentClimateRef'] + + @property + def current_operation(self): + """Return current hvac mode ie. auto, auxHeatOnly, cool, heat, off.""" + return self.thermostat['settings']['hvacMode'] + + @property + def fan_min_on_time(self): + """Return current fan minimum on time.""" + return self.thermostat['settings']['fanMinOnTime'] + + @property + def device_state_attributes(self): + """Return device specific state attributes.""" + # Move these to Thermostat Device and make them global + return { + "humidity": self.current_humidity, + "fan": self.fan, + "mode": self.mode, + "operation_mode": self.current_operation, + "fan_min_on_time": self.fan_min_on_time + } + + @property + def is_away_mode_on(self): + """Return true if away mode is on.""" + mode = self.mode + events = self.thermostat['events'] + for event in events: + if event['running']: + mode = event['holdClimateRef'] + break + return 'away' in mode + + def turn_away_mode_on(self): + """Turn away on.""" + if self.hold_temp: + self.data.ecobee.set_climate_hold(self.thermostat_index, + "away", "indefinite") + else: + self.data.ecobee.set_climate_hold(self.thermostat_index, "away") + + def turn_away_mode_off(self): + """Turn away off.""" + self.data.ecobee.resume_program(self.thermostat_index) + + def set_temperature(self, temperature): + """Set new target temperature.""" + temperature = int(temperature) + low_temp = temperature - 1 + high_temp = temperature + 1 + if self.hold_temp: + self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp, + high_temp, "indefinite") + else: + self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp, + high_temp) + + def set_operation_mode(self, operation_mode): + """Set HVAC mode (auto, auxHeatOnly, cool, heat, off).""" + self.data.ecobee.set_hvac_mode(self.thermostat_index, operation_mode) + + def set_fan_min_on_time(self, fan_min_on_time): + """Set the minimum fan on time.""" + self.data.ecobee.set_fan_min_on_time(self.thermostat_index, + fan_min_on_time) + + # Home and Sleep mode aren't used in UI yet: + + # def turn_home_mode_on(self): + # """ Turns home mode on. """ + # self.data.ecobee.set_climate_hold(self.thermostat_index, "home") + + # def turn_home_mode_off(self): + # """ Turns home mode off. """ + # self.data.ecobee.resume_program(self.thermostat_index) + + # def turn_sleep_mode_on(self): + # """ Turns sleep mode on. """ + # self.data.ecobee.set_climate_hold(self.thermostat_index, "sleep") + + # def turn_sleep_mode_off(self): + # """ Turns sleep mode off. """ + # self.data.ecobee.resume_program(self.thermostat_index) diff --git a/homeassistant/components/climate/eq3btsmart.py b/homeassistant/components/climate/eq3btsmart.py new file mode 100644 index 00000000000..01114972811 --- /dev/null +++ b/homeassistant/components/climate/eq3btsmart.py @@ -0,0 +1,90 @@ +""" +Support for eq3 Bluetooth Smart thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.eq3btsmart/ +""" +import logging + +from homeassistant.components.climate import ClimateDevice +from homeassistant.const import TEMP_CELSIUS +from homeassistant.util.temperature import convert + +REQUIREMENTS = ['bluepy_devices==0.2.0'] + +CONF_MAC = 'mac' +CONF_DEVICES = 'devices' +CONF_ID = 'id' + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the eq3 BLE thermostats.""" + devices = [] + + for name, device_cfg in config[CONF_DEVICES].items(): + mac = device_cfg[CONF_MAC] + devices.append(EQ3BTSmartThermostat(mac, name)) + + add_devices(devices) + return True + + +# pylint: disable=too-many-instance-attributes, import-error, abstract-method +class EQ3BTSmartThermostat(ClimateDevice): + """Representation of a EQ3 Bluetooth Smart thermostat.""" + + def __init__(self, _mac, _name): + """Initialize the thermostat.""" + from bluepy_devices.devices import eq3btsmart + + self._name = _name + + self._thermostat = eq3btsmart.EQ3BTSmartThermostat(_mac) + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement that is used.""" + return TEMP_CELSIUS + + @property + def current_temperature(self): + """Can not report temperature, so return target_temperature.""" + return self.target_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._thermostat.target_temperature + + def set_temperature(self, temperature): + """Set new target temperature.""" + self._thermostat.target_temperature = temperature + + @property + def device_state_attributes(self): + """Return the device specific state attributes.""" + return {"mode": self._thermostat.mode, + "mode_readable": self._thermostat.mode_readable} + + @property + def min_temp(self): + """Return the minimum temperature.""" + return convert(self._thermostat.min_temp, TEMP_CELSIUS, + self.unit_of_measurement) + + @property + def max_temp(self): + """Return the maximum temperature.""" + return convert(self._thermostat.max_temp, TEMP_CELSIUS, + self.unit_of_measurement) + + def update(self): + """Update the data from the thermostat.""" + self._thermostat.update() diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py new file mode 100644 index 00000000000..11e6707ad47 --- /dev/null +++ b/homeassistant/components/climate/generic_thermostat.py @@ -0,0 +1,216 @@ +""" +Adds support for generic thermostat units. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.generic_thermostat/ +""" +import logging +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components import switch +from homeassistant.components.climate import ( + STATE_HEAT, STATE_COOL, STATE_IDLE, ClimateDevice) +from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF +from homeassistant.helpers import condition +from homeassistant.helpers.event import track_state_change + +DEPENDENCIES = ['switch', 'sensor'] + +TOL_TEMP = 0.3 + +CONF_NAME = 'name' +DEFAULT_NAME = 'Generic Thermostat' +CONF_HEATER = 'heater' +CONF_SENSOR = 'target_sensor' +CONF_MIN_TEMP = 'min_temp' +CONF_MAX_TEMP = 'max_temp' +CONF_TARGET_TEMP = 'target_temp' +CONF_AC_MODE = 'ac_mode' +CONF_MIN_DUR = 'min_cycle_duration' + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required("platform"): "generic_thermostat", + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_HEATER): cv.entity_id, + vol.Required(CONF_SENSOR): cv.entity_id, + vol.Optional(CONF_MIN_TEMP): vol.Coerce(float), + vol.Optional(CONF_MAX_TEMP): vol.Coerce(float), + vol.Optional(CONF_TARGET_TEMP): vol.Coerce(float), + vol.Optional(CONF_AC_MODE): vol.Coerce(bool), + vol.Optional(CONF_MIN_DUR): vol.All(cv.time_period, cv.positive_timedelta), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the generic thermostat.""" + name = config.get(CONF_NAME) + heater_entity_id = config.get(CONF_HEATER) + sensor_entity_id = config.get(CONF_SENSOR) + min_temp = config.get(CONF_MIN_TEMP) + max_temp = config.get(CONF_MAX_TEMP) + target_temp = config.get(CONF_TARGET_TEMP) + ac_mode = config.get(CONF_AC_MODE) + min_cycle_duration = config.get(CONF_MIN_DUR) + + add_devices([GenericThermostat(hass, name, heater_entity_id, + sensor_entity_id, min_temp, + max_temp, target_temp, ac_mode, + min_cycle_duration)]) + + +# pylint: disable=too-many-instance-attributes, abstract-method +class GenericThermostat(ClimateDevice): + """Representation of a GenericThermostat device.""" + + # pylint: disable=too-many-arguments + def __init__(self, hass, name, heater_entity_id, sensor_entity_id, + min_temp, max_temp, target_temp, ac_mode, min_cycle_duration): + """Initialize the thermostat.""" + self.hass = hass + self._name = name + self.heater_entity_id = heater_entity_id + self.ac_mode = ac_mode + self.min_cycle_duration = min_cycle_duration + + self._active = False + self._cur_temp = None + self._min_temp = min_temp + self._max_temp = max_temp + self._target_temp = target_temp + self._unit = hass.config.units.temperature_unit + + track_state_change(hass, sensor_entity_id, self._sensor_changed) + + sensor_state = hass.states.get(sensor_entity_id) + if sensor_state: + self._update_temp(sensor_state) + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the thermostat.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return self._unit + + @property + def current_temperature(self): + """Return the sensor temperature.""" + return self._cur_temp + + @property + def operation(self): + """Return current operation ie. heat, cool, idle.""" + if self.ac_mode: + cooling = self._active and self._is_device_active + return STATE_COOL if cooling else STATE_IDLE + else: + heating = self._active and self._is_device_active + return STATE_HEAT if heating else STATE_IDLE + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temp + + def set_temperature(self, temperature): + """Set new target temperature.""" + self._target_temp = temperature + self._control_heating() + self.update_ha_state() + + @property + def min_temp(self): + """Return the minimum temperature.""" + # pylint: disable=no-member + if self._min_temp: + return self._min_temp + else: + # get default temp from super class + return ClimateDevice.min_temp.fget(self) + + @property + def max_temp(self): + """Return the maximum temperature.""" + # pylint: disable=no-member + if self._min_temp: + return self._max_temp + else: + # Get default temp from super class + return ClimateDevice.max_temp.fget(self) + + def _sensor_changed(self, entity_id, old_state, new_state): + """Called when temperature changes.""" + if new_state is None: + return + + self._update_temp(new_state) + self._control_heating() + self.update_ha_state() + + def _update_temp(self, state): + """Update thermostat with latest state from sensor.""" + unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + + try: + self._cur_temp = self.hass.config.units.temperature( + float(state.state), unit) + except ValueError as ex: + _LOGGER.error('Unable to update from sensor: %s', ex) + + def _control_heating(self): + """Check if we need to turn heating on or off.""" + if not self._active and None not in (self._cur_temp, + self._target_temp): + self._active = True + _LOGGER.info('Obtained current and target temperature. ' + 'Generic thermostat active.') + + if not self._active: + return + + if self.min_cycle_duration: + if self._is_device_active: + current_state = STATE_ON + else: + current_state = STATE_OFF + long_enough = condition.state(self.hass, self.heater_entity_id, + current_state, + self.min_cycle_duration) + if not long_enough: + return + + if self.ac_mode: + too_hot = self._cur_temp - self._target_temp > TOL_TEMP + is_cooling = self._is_device_active + if too_hot and not is_cooling: + _LOGGER.info('Turning on AC %s', self.heater_entity_id) + switch.turn_on(self.hass, self.heater_entity_id) + elif not too_hot and is_cooling: + _LOGGER.info('Turning off AC %s', self.heater_entity_id) + switch.turn_off(self.hass, self.heater_entity_id) + else: + too_cold = self._target_temp - self._cur_temp > TOL_TEMP + is_heating = self._is_device_active + + if too_cold and not is_heating: + _LOGGER.info('Turning on heater %s', self.heater_entity_id) + switch.turn_on(self.hass, self.heater_entity_id) + elif not too_cold and is_heating: + _LOGGER.info('Turning off heater %s', self.heater_entity_id) + switch.turn_off(self.hass, self.heater_entity_id) + + @property + def _is_device_active(self): + """If the toggleable device is currently active.""" + return switch.is_on(self.hass, self.heater_entity_id) diff --git a/homeassistant/components/climate/heatmiser.py b/homeassistant/components/climate/heatmiser.py new file mode 100644 index 00000000000..c7dd5534f57 --- /dev/null +++ b/homeassistant/components/climate/heatmiser.py @@ -0,0 +1,114 @@ +""" +Support for the PRT Heatmiser themostats using the V3 protocol. + +See https://github.com/andylockran/heatmiserV3 for more info on the +heatmiserV3 module dependency. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.heatmiser/ +""" +import logging + +from homeassistant.components.climate import ClimateDevice +from homeassistant.const import TEMP_CELSIUS + +CONF_IPADDRESS = 'ipaddress' +CONF_PORT = 'port' +CONF_TSTATS = 'tstats' + +REQUIREMENTS = ["heatmiserV3==0.9.1"] + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the heatmiser thermostat.""" + from heatmiserV3 import heatmiser, connection + + ipaddress = str(config[CONF_IPADDRESS]) + port = str(config[CONF_PORT]) + + if ipaddress is None or port is None: + _LOGGER.error("Missing required configuration items %s or %s", + CONF_IPADDRESS, CONF_PORT) + return False + + serport = connection.connection(ipaddress, port) + serport.open() + + tstats = [] + if CONF_TSTATS in config: + tstats = config[CONF_TSTATS] + + if tstats is None: + _LOGGER.error("No thermostats configured.") + return False + + for tstat in tstats: + add_devices([ + HeatmiserV3Thermostat( + heatmiser, + tstat.get("id"), + tstat.get("name"), + serport) + ]) + return + + +class HeatmiserV3Thermostat(ClimateDevice): + """Representation of a HeatmiserV3 thermostat.""" + + # pylint: disable=too-many-instance-attributes, abstract-method + def __init__(self, heatmiser, device, name, serport): + """Initialize the thermostat.""" + self.heatmiser = heatmiser + self.device = device + self.serport = serport + self._current_temperature = None + self._name = name + self._id = device + self.dcb = None + self.update() + self._target_temperature = int(self.dcb.get("roomset")) + + @property + def name(self): + """Return the name of the thermostat, if any.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement which this thermostat uses.""" + return TEMP_CELSIUS + + @property + def current_temperature(self): + """Return the current temperature.""" + if self.dcb is not None: + low = self.dcb.get("floortemplow ") + high = self.dcb.get("floortemphigh") + temp = (high*256 + low)/10.0 + self._current_temperature = temp + else: + self._current_temperature = None + return self._current_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temperature + + def set_temperature(self, temperature): + """Set new target temperature.""" + temperature = int(temperature) + self.heatmiser.hmSendAddress( + self._id, + 18, + temperature, + 1, + self.serport) + self._target_temperature = int(temperature) + + def update(self): + """Get the latest data.""" + self.dcb = self.heatmiser.hmReadAddress(self._id, 'prt', self.serport) diff --git a/homeassistant/components/climate/homematic.py b/homeassistant/components/climate/homematic.py new file mode 100644 index 00000000000..da160bab56e --- /dev/null +++ b/homeassistant/components/climate/homematic.py @@ -0,0 +1,90 @@ +""" +Support for Homematic thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.homematic/ +""" +import logging +import homeassistant.components.homematic as homematic +from homeassistant.components.climate import ClimateDevice +from homeassistant.util.temperature import convert +from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN + +DEPENDENCIES = ['homematic'] + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_callback_devices, discovery_info=None): + """Setup the Homematic thermostat platform.""" + if discovery_info is None: + return + + return homematic.setup_hmdevice_discovery_helper(HMThermostat, + discovery_info, + add_callback_devices) + + +# pylint: disable=abstract-method +class HMThermostat(homematic.HMDevice, ClimateDevice): + """Representation of a Homematic thermostat.""" + + @property + def unit_of_measurement(self): + """Return the unit of measurement that is used.""" + return TEMP_CELSIUS + + @property + def current_temperature(self): + """Return the current temperature.""" + if not self.available: + return None + return self._data["ACTUAL_TEMPERATURE"] + + @property + def target_temperature(self): + """Return the target temperature.""" + if not self.available: + return None + return self._data["SET_TEMPERATURE"] + + def set_temperature(self, temperature): + """Set new target temperature.""" + if not self.available: + return None + self._hmdevice.set_temperature(temperature) + + @property + def min_temp(self): + """Return the minimum temperature - 4.5 means off.""" + return convert(4.5, TEMP_CELSIUS, self.unit_of_measurement) + + @property + def max_temp(self): + """Return the maximum temperature - 30.5 means on.""" + return convert(30.5, TEMP_CELSIUS, self.unit_of_measurement) + + def _check_hm_to_ha_object(self): + """Check if possible to use the Homematic object as this HA type.""" + from pyhomematic.devicetypes.thermostats import HMThermostat\ + as pyHMThermostat + + # Check compatibility from HMDevice + if not super()._check_hm_to_ha_object(): + return False + + # Check if the Homematic device correct for this HA device + if isinstance(self._hmdevice, pyHMThermostat): + return True + + _LOGGER.critical("This %s can't be use as thermostat", self._name) + return False + + def _init_data_struct(self): + """Generate a data dict (self._data) from the Homematic metadata.""" + super()._init_data_struct() + + # Add state to data dict + self._data.update({"CONTROL_MODE": STATE_UNKNOWN, + "SET_TEMPERATURE": STATE_UNKNOWN, + "ACTUAL_TEMPERATURE": STATE_UNKNOWN}) diff --git a/homeassistant/components/climate/honeywell.py b/homeassistant/components/climate/honeywell.py new file mode 100644 index 00000000000..1efce2b95de --- /dev/null +++ b/homeassistant/components/climate/honeywell.py @@ -0,0 +1,266 @@ +""" +Support for Honeywell Round Connected and Honeywell Evohome thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.honeywell/ +""" +import logging +import socket + +from homeassistant.components.climate import ClimateDevice +from homeassistant.const import ( + CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT) + +REQUIREMENTS = ['evohomeclient==0.2.5', + 'somecomfort==0.2.1'] + +_LOGGER = logging.getLogger(__name__) + +CONF_AWAY_TEMP = "away_temperature" +DEFAULT_AWAY_TEMP = 16 + + +def _setup_round(username, password, config, add_devices): + """Setup rounding function.""" + from evohomeclient import EvohomeClient + + try: + away_temp = float(config.get(CONF_AWAY_TEMP, DEFAULT_AWAY_TEMP)) + except ValueError: + _LOGGER.error("value entered for item %s should convert to a number", + CONF_AWAY_TEMP) + return False + + evo_api = EvohomeClient(username, password) + + try: + zones = evo_api.temperatures(force_refresh=True) + for i, zone in enumerate(zones): + add_devices([RoundThermostat(evo_api, + zone['id'], + i == 0, + away_temp)]) + except socket.error: + _LOGGER.error( + "Connection error logging into the honeywell evohome web service" + ) + return False + return True + + +# config will be used later +def _setup_us(username, password, config, add_devices): + """Setup user.""" + import somecomfort + + try: + client = somecomfort.SomeComfort(username, password) + except somecomfort.AuthError: + _LOGGER.error('Failed to login to honeywell account %s', username) + return False + except somecomfort.SomeComfortError as ex: + _LOGGER.error('Failed to initialize honeywell client: %s', str(ex)) + return False + + dev_id = config.get('thermostat') + loc_id = config.get('location') + + add_devices([HoneywellUSThermostat(client, device) + for location in client.locations_by_id.values() + for device in location.devices_by_id.values() + if ((not loc_id or location.locationid == loc_id) and + (not dev_id or device.deviceid == dev_id))]) + return True + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the honeywel thermostat.""" + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + region = config.get('region', 'eu').lower() + + if username is None or password is None: + _LOGGER.error("Missing required configuration items %s or %s", + CONF_USERNAME, CONF_PASSWORD) + return False + if region not in ('us', 'eu'): + _LOGGER.error('Region `%s` is invalid (use either us or eu)', region) + return False + + if region == 'us': + return _setup_us(username, password, config, add_devices) + else: + return _setup_round(username, password, config, add_devices) + + +class RoundThermostat(ClimateDevice): + """Representation of a Honeywell Round Connected thermostat.""" + + # pylint: disable=too-many-instance-attributes, abstract-method + def __init__(self, device, zone_id, master, away_temp): + """Initialize the thermostat.""" + self.device = device + self._current_temperature = None + self._target_temperature = None + self._name = "round connected" + self._id = zone_id + self._master = master + self._is_dhw = False + self._away_temp = away_temp + self._away = False + self.update() + + @property + def name(self): + """Return the name of the honeywell, if any.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return TEMP_CELSIUS + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + if self._is_dhw: + return None + return self._target_temperature + + def set_temperature(self, temperature): + """Set new target temperature.""" + self.device.set_temperature(self._name, temperature) + + @property + def current_operation(self: ClimateDevice) -> str: + """Get the current operation of the system.""" + return getattr(self.device, 'system_mode', None) + + @property + def is_away_mode_on(self): + """Return true if away mode is on.""" + return self._away + + def set_operation_mode(self: ClimateDevice, operation_mode: str) -> None: + """Set the HVAC mode for the thermostat.""" + if hasattr(self.device, 'system_mode'): + self.device.system_mode = operation_mode + + def turn_away_mode_on(self): + """Turn away on. + + Evohome does have a proprietary away mode, but it doesn't really work + the way it should. For example: If you set a temperature manually + it doesn't get overwritten when away mode is switched on. + """ + self._away = True + self.device.set_temperature(self._name, self._away_temp) + + def turn_away_mode_off(self): + """Turn away off.""" + self._away = False + self.device.cancel_temp_override(self._name) + + def update(self): + """Get the latest date.""" + try: + # Only refresh if this is the "master" device, + # others will pick up the cache + for val in self.device.temperatures(force_refresh=self._master): + if val['id'] == self._id: + data = val + + except StopIteration: + _LOGGER.error("Did not receive any temperature data from the " + "evohomeclient API.") + return + + self._current_temperature = data['temp'] + self._target_temperature = data['setpoint'] + if data['thermostat'] == "DOMESTIC_HOT_WATER": + self._name = "Hot Water" + self._is_dhw = True + else: + self._name = data['name'] + self._is_dhw = False + + +# pylint: disable=abstract-method +class HoneywellUSThermostat(ClimateDevice): + """Representation of a Honeywell US Thermostat.""" + + def __init__(self, client, device): + """Initialize the thermostat.""" + self._client = client + self._device = device + + @property + def is_fan_on(self): + """Return true if fan is on.""" + return self._device.fan_running + + @property + def name(self): + """Return the name of the honeywell, if any.""" + return self._device.name + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return (TEMP_CELSIUS if self._device.temperature_unit == 'C' + else TEMP_FAHRENHEIT) + + @property + def current_temperature(self): + """Return the current temperature.""" + self._device.refresh() + return self._device.current_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + if self._device.system_mode == 'cool': + return self._device.setpoint_cool + else: + return self._device.setpoint_heat + + @property + def current_operation(self: ClimateDevice) -> str: + """Return current operation ie. heat, cool, idle.""" + return getattr(self._device, 'system_mode', None) + + def set_temperature(self, temperature): + """Set target temperature.""" + import somecomfort + try: + if self._device.system_mode == 'cool': + self._device.setpoint_cool = temperature + else: + self._device.setpoint_heat = temperature + except somecomfort.SomeComfortError: + _LOGGER.error('Temperature %.1f out of range', temperature) + + @property + def device_state_attributes(self): + """Return the device specific state attributes.""" + return {'fan': (self.is_fan_on and 'running' or 'idle'), + 'fanmode': self._device.fan_mode, + 'system_mode': self._device.system_mode} + + def turn_away_mode_on(self): + """Turn away on.""" + pass + + def turn_away_mode_off(self): + """Turn away off.""" + pass + + def set_operation_mode(self: ClimateDevice, operation_mode: str) -> None: + """Set the system mode (Cool, Heat, etc).""" + if hasattr(self._device, 'system_mode'): + self._device.system_mode = operation_mode diff --git a/homeassistant/components/climate/knx.py b/homeassistant/components/climate/knx.py new file mode 100644 index 00000000000..10f02d80cc7 --- /dev/null +++ b/homeassistant/components/climate/knx.py @@ -0,0 +1,83 @@ +""" +Support for KNX thermostats. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/knx/ +""" +import logging + +from homeassistant.components.climate import ClimateDevice +from homeassistant.const import TEMP_CELSIUS + +from homeassistant.components.knx import ( + KNXConfig, KNXMultiAddressDevice) + +DEPENDENCIES = ["knx"] + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Create and add an entity based on the configuration.""" + add_entities([ + KNXThermostat(hass, KNXConfig(config)) + ]) + + +class KNXThermostat(KNXMultiAddressDevice, ClimateDevice): + """Representation of a KNX thermostat. + + A KNX thermostat will has the following parameters: + - temperature (current temperature) + - setpoint (target temperature in HASS terms) + - operation mode selection (comfort/night/frost protection) + + This version supports only polling. Messages from the KNX bus do not + automatically update the state of the thermostat (to be implemented + in future releases) + """ + + def __init__(self, hass, config): + """Initialize the thermostat based on the given configuration.""" + KNXMultiAddressDevice.__init__(self, hass, config, + ["temperature", "setpoint"], + ["mode"]) + + self._unit_of_measurement = TEMP_CELSIUS # KNX always used celsius + self._away = False # not yet supported + self._is_fan_on = False # not yet supported + + @property + def should_poll(self): + """Polling is needed for the KNX thermostat.""" + return True + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return self._unit_of_measurement + + @property + def current_temperature(self): + """Return the current temperature.""" + from knxip.conversion import knx2_to_float + + return knx2_to_float(self.value("temperature")) + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + from knxip.conversion import knx2_to_float + + return knx2_to_float(self.value("setpoint")) + + def set_temperature(self, temperature): + """Set new target temperature.""" + from knxip.conversion import float_to_knx2 + + self.set_value("setpoint", float_to_knx2(temperature)) + _LOGGER.debug("Set target temperature to %s", temperature) + + def set_operation_mode(self, operation_mode): + """Set operation mode.""" + raise NotImplementedError() diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py new file mode 100644 index 00000000000..39746bff601 --- /dev/null +++ b/homeassistant/components/climate/nest.py @@ -0,0 +1,189 @@ +""" +Support for Nest thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.nest/ +""" +import voluptuous as vol + +import homeassistant.components.nest as nest +from homeassistant.components.climate import ( + STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice) +from homeassistant.const import TEMP_CELSIUS, CONF_PLATFORM, CONF_SCAN_INTERVAL + +DEPENDENCIES = ['nest'] + +PLATFORM_SCHEMA = vol.Schema({ + vol.Required(CONF_PLATFORM): nest.DOMAIN, + vol.Optional(CONF_SCAN_INTERVAL): + vol.All(vol.Coerce(int), vol.Range(min=1)), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Nest thermostat.""" + add_devices([NestThermostat(structure, device) + for structure, device in nest.devices()]) + + +# pylint: disable=abstract-method +class NestThermostat(ClimateDevice): + """Representation of a Nest thermostat.""" + + def __init__(self, structure, device): + """Initialize the thermostat.""" + self.structure = structure + self.device = device + + @property + def name(self): + """Return the name of the nest, if any.""" + location = self.device.where + name = self.device.name + if location is None: + return name + else: + if name == '': + return location.capitalize() + else: + return location.capitalize() + '(' + name + ')' + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return TEMP_CELSIUS + + @property + def device_state_attributes(self): + """Return the device specific state attributes.""" + # Move these to Thermostat Device and make them global + return { + "humidity": self.device.humidity, + "target_humidity": self.device.target_humidity, + "mode": self.device.mode + } + + @property + def current_temperature(self): + """Return the current temperature.""" + return self.device.temperature + + @property + def operation(self): + """Return current operation ie. heat, cool, idle.""" + if self.device.hvac_ac_state is True: + return STATE_COOL + elif self.device.hvac_heater_state is True: + return STATE_HEAT + else: + return STATE_IDLE + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + if self.device.mode == 'range': + low, high = self.target_temperature_low, \ + self.target_temperature_high + if self.operation == STATE_COOL: + temp = high + elif self.operation == STATE_HEAT: + temp = low + else: + # If the outside temp is lower than the current temp, consider + # the 'low' temp to the target, otherwise use the high temp + if (self.device.structure.weather.current.temperature < + self.current_temperature): + temp = low + else: + temp = high + else: + if self.is_away_mode_on: + # away_temperature is a low, high tuple. Only one should be set + # if not in range mode, the other will be None + temp = self.device.away_temperature[0] or \ + self.device.away_temperature[1] + else: + temp = self.device.target + + return temp + + @property + def target_temperature_low(self): + """Return the lower bound temperature we try to reach.""" + if self.is_away_mode_on and self.device.away_temperature[0]: + # away_temperature is always a low, high tuple + return self.device.away_temperature[0] + if self.device.mode == 'range': + return self.device.target[0] + return self.target_temperature + + @property + def target_temperature_high(self): + """Return the upper bound temperature we try to reach.""" + if self.is_away_mode_on and self.device.away_temperature[1]: + # away_temperature is always a low, high tuple + return self.device.away_temperature[1] + if self.device.mode == 'range': + return self.device.target[1] + return self.target_temperature + + @property + def is_away_mode_on(self): + """Return if away mode is on.""" + return self.structure.away + + def set_temperature(self, temperature): + """Set new target temperature.""" + if self.device.mode == 'range': + if self.target_temperature == self.target_temperature_low: + temperature = (temperature, self.target_temperature_high) + elif self.target_temperature == self.target_temperature_high: + temperature = (self.target_temperature_low, temperature) + self.device.target = temperature + + def set_operation_mode(self, operation_mode): + """Set operation mode.""" + self.device.mode = operation_mode + + def turn_away_mode_on(self): + """Turn away on.""" + self.structure.away = True + + def turn_away_mode_off(self): + """Turn away off.""" + self.structure.away = False + + @property + def is_fan_on(self): + """Return whether the fan is on.""" + return self.device.fan + + def turn_fan_on(self): + """Turn fan on.""" + self.device.fan = True + + def turn_fan_off(self): + """Turn fan off.""" + self.device.fan = False + + @property + def min_temp(self): + """Identify min_temp in Nest API or defaults if not available.""" + temp = self.device.away_temperature.low + if temp is None: + return super().min_temp + else: + return temp + + @property + def max_temp(self): + """Identify max_temp in Nest API or defaults if not available.""" + temp = self.device.away_temperature.high + if temp is None: + return super().max_temp + else: + return temp + + def update(self): + """Python-nest has its own mechanism for staying up to date.""" + pass diff --git a/homeassistant/components/climate/proliphix.py b/homeassistant/components/climate/proliphix.py new file mode 100644 index 00000000000..c6e8ed69617 --- /dev/null +++ b/homeassistant/components/climate/proliphix.py @@ -0,0 +1,90 @@ +""" +Support for Proliphix NT10e Thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.proliphix/ +""" +from homeassistant.components.climate import ( + STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice) +from homeassistant.const import ( + CONF_HOST, CONF_PASSWORD, CONF_USERNAME, TEMP_FAHRENHEIT) + +REQUIREMENTS = ['proliphix==0.3.1'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Proliphix thermostats.""" + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + host = config.get(CONF_HOST) + + import proliphix + + pdp = proliphix.PDP(host, username, password) + + add_devices([ + ProliphixThermostat(pdp) + ]) + + +# pylint: disable=abstract-method +class ProliphixThermostat(ClimateDevice): + """Representation a Proliphix thermostat.""" + + def __init__(self, pdp): + """Initialize the thermostat.""" + self._pdp = pdp + # initial data + self._pdp.update() + self._name = self._pdp.name + + @property + def should_poll(self): + """Polling needed for thermostat.""" + return True + + def update(self): + """Update the data from the thermostat.""" + self._pdp.update() + + @property + def name(self): + """Return the name of the thermostat.""" + return self._name + + @property + def device_state_attributes(self): + """Return the device specific state attributes.""" + return { + "fan": self._pdp.fan_state + } + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return TEMP_FAHRENHEIT + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._pdp.cur_temp + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._pdp.setback + + @property + def current_operation(self): + """Return the current state of the thermostat.""" + state = self._pdp.hvac_state + if state in (1, 2): + return STATE_IDLE + elif state == 3: + return STATE_HEAT + elif state == 6: + return STATE_COOL + + def set_temperature(self, temperature): + """Set new target temperature.""" + self._pdp.setback = temperature diff --git a/homeassistant/components/climate/radiotherm.py b/homeassistant/components/climate/radiotherm.py new file mode 100644 index 00000000000..deee3d53f3f --- /dev/null +++ b/homeassistant/components/climate/radiotherm.py @@ -0,0 +1,136 @@ +""" +Support for Radio Thermostat wifi-enabled home thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.radiotherm/ +""" +import datetime +import logging +from urllib.error import URLError + +from homeassistant.components.climate import ( + STATE_AUTO, STATE_COOL, STATE_HEAT, STATE_IDLE, STATE_OFF, + ClimateDevice) +from homeassistant.const import CONF_HOST, TEMP_FAHRENHEIT + +REQUIREMENTS = ['radiotherm==1.2'] +HOLD_TEMP = 'hold_temp' +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Radio Thermostat.""" + import radiotherm + + hosts = [] + if CONF_HOST in config: + hosts = config[CONF_HOST] + else: + hosts.append(radiotherm.discover.discover_address()) + + if hosts is None: + _LOGGER.error("No radiotherm thermostats detected.") + return False + + hold_temp = config.get(HOLD_TEMP, False) + tstats = [] + + for host in hosts: + try: + tstat = radiotherm.get_thermostat(host) + tstats.append(RadioThermostat(tstat, hold_temp)) + except (URLError, OSError): + _LOGGER.exception("Unable to connect to Radio Thermostat: %s", + host) + + add_devices(tstats) + + +# pylint: disable=abstract-method +class RadioThermostat(ClimateDevice): + """Representation of a Radio Thermostat.""" + + def __init__(self, device, hold_temp): + """Initialize the thermostat.""" + self.device = device + self.set_time() + self._target_temperature = None + self._current_temperature = None + self._current_operation = STATE_IDLE + self._name = None + self.hold_temp = hold_temp + self.update() + + @property + def name(self): + """Return the name of the Radio Thermostat.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return TEMP_FAHRENHEIT + + @property + def device_state_attributes(self): + """Return the device specific state attributes.""" + return { + "fan": self.device.fmode['human'], + "mode": self.device.tmode['human'] + } + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def current_operation(self): + """Return the current operation. head, cool idle.""" + return self._current_operation + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temperature + + def update(self): + """Update the data from the thermostat.""" + self._current_temperature = self.device.temp['raw'] + self._name = self.device.name['raw'] + if self.device.tmode['human'] == 'Cool': + self._target_temperature = self.device.t_cool['raw'] + self._current_operation = STATE_COOL + elif self.device.tmode['human'] == 'Heat': + self._target_temperature = self.device.t_heat['raw'] + self._current_operation = STATE_HEAT + else: + self._current_operation = STATE_IDLE + + def set_temperature(self, temperature): + """Set new target temperature.""" + if self._current_operation == STATE_COOL: + self.device.t_cool = temperature + elif self._current_operation == STATE_HEAT: + self.device.t_heat = temperature + if self.hold_temp: + self.device.hold = 1 + else: + self.device.hold = 0 + + def set_time(self): + """Set device time.""" + now = datetime.datetime.now() + self.device.time = {'day': now.weekday(), + 'hour': now.hour, 'minute': now.minute} + + def set_operation_mode(self, operation_mode): + """Set operation mode (auto, cool, heat, off).""" + if operation_mode == STATE_OFF: + self.device.tmode = 0 + elif operation_mode == STATE_AUTO: + self.device.tmode = 3 + elif operation_mode == STATE_COOL: + self.device.t_cool = self._target_temperature + elif operation_mode == STATE_HEAT: + self.device.t_heat = self._target_temperature diff --git a/homeassistant/components/climate/services.yaml b/homeassistant/components/climate/services.yaml new file mode 100644 index 00000000000..3a037d2a48b --- /dev/null +++ b/homeassistant/components/climate/services.yaml @@ -0,0 +1,84 @@ +set_aux_heat: + description: Turn auxillary heater on/off for climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climate.kitchen' + + aux_heat: + description: New value of axillary heater + example: true + +set_away_mode: + description: Turn away mode on/off for climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climate.kitchen' + + away_mode: + description: New value of away mode + example: true + +set_temperature: + description: Set target temperature of climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climate.kitchen' + + temperature: + description: New target temperature for hvac + example: 25 + +set_humidity: + description: Set target humidity of climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climate.kitchen' + + humidity: + description: New target humidity for climate device + example: 60 + +set_fan_mode: + description: Set fan operation for climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climate.nest' + + fan: + description: New value of fan mode + example: On Low + +set_operation_mode: + description: Set operation mode for climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: 'climet.nest' + + operation_mode: + description: New value of operation mode + example: Heat + + +set_swing_mode: + description: Set swing operation for climate device + + fields: + entity_id: + description: Name(s) of entities to change + example: '.nest' + + swing_mode: + description: New value of swing mode + example: 1 diff --git a/homeassistant/components/climate/zwave.py b/homeassistant/components/climate/zwave.py new file mode 100755 index 00000000000..54ca57e2163 --- /dev/null +++ b/homeassistant/components/climate/zwave.py @@ -0,0 +1,253 @@ +""" +Support for ZWave climate devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.zwave/ +""" +# Because we do not compile openzwave on CI +# 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 import zwave +from homeassistant.const import (TEMP_FAHRENHEIT, TEMP_CELSIUS) + +_LOGGER = logging.getLogger(__name__) + +CONF_NAME = 'name' +DEFAULT_NAME = 'ZWave Climate' + +REMOTEC = 0x5254 +REMOTEC_ZXT_120 = 0x8377 +REMOTEC_ZXT_120_THERMOSTAT = (REMOTEC, REMOTEC_ZXT_120) + +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' + +DEVICE_MAPPINGS = { + REMOTEC_ZXT_120_THERMOSTAT: WORKAROUND_ZXT_120 +} + +ZXT_120_SET_TEMP = { + 'Heat': 1, + 'Cool': 2, + 'Dry Air': 8, + 'Auto Changeover': 10 +} + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the ZWave Climate devices.""" + if discovery_info is None or zwave.NETWORK is None: + _LOGGER.debug("No discovery_info=%s or no NETWORK=%s", + discovery_info, zwave.NETWORK) + return + + node = zwave.NETWORK.nodes[discovery_info[ATTR_NODE_ID]] + value = node.values[discovery_info[ATTR_VALUE_ID]] + value.set_change_verified(False) + add_devices([ZWaveClimate(value)]) + _LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s", + discovery_info, zwave.NETWORK) + + +# pylint: disable=too-many-arguments, abstract-method +class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): + """Represents a ZWave Climate device.""" + + # pylint: disable=too-many-public-methods, too-many-instance-attributes + def __init__(self, value): + """Initialize the zwave climate device.""" + from openzwave.network import ZWaveNetwork + from pydispatch import dispatcher + ZWaveDeviceEntity.__init__(self, value, DOMAIN) + self._node = value.node + self._target_temperature = None + self._current_temperature = None + self._current_operation = None + self._operation_list = None + self._current_fan_mode = None + self._fan_list = None + self._current_swing_mode = None + self._swing_list = None + self._unit = None + self._index = None + self._zxt_120 = None + self.update_properties() + # register listener + dispatcher.connect( + self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) + # Make sure that we have values for the key before converting to int + if (value.node.manufacturer_id.strip() and + value.node.product_id.strip()): + specific_sensor_key = (int(value.node.manufacturer_id, 16), + int(value.node.product_id, 16)) + + if specific_sensor_key in DEVICE_MAPPINGS: + if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND_ZXT_120: + _LOGGER.debug("Remotec ZXT-120 Zwave Thermostat" + " workaround") + self._zxt_120 = 1 + + def value_changed(self, value): + """Called when a value has changed on the network.""" + if self._value.value_id == value.value_id or \ + self._value.node == value.node: + self.update_properties() + self.update_ha_state() + _LOGGER.debug("Value changed on network %s", value) + + def update_properties(self): + """Callback on data change for the registered node/value pair.""" + # Set point + temps = [] + for value in self._node.get_values( + class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): + temps.append(int(value.data)) + if value.index == self._index: + self._target_temperature = int(value.data) + self._target_temperature_high = max(temps) + self._target_temperature_low = min(temps) + # Operation Mode + for value in self._node.get_values( + class_id=COMMAND_CLASS_THERMOSTAT_MODE).values(): + self._current_operation = value.data + self._operation_list = list(value.data_items) + _LOGGER.debug("self._operation_list=%s", self._operation_list) + _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(): + 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(): + self._current_fan_mode = value.data + self._fan_list = list(value.data_items) + _LOGGER.debug("self._fan_list=%s", self._fan_list) + _LOGGER.debug("self._current_fan_mode=%s", + 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: + 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) + + @property + def should_poll(self): + """No polling on ZWave.""" + return False + + @property + def current_fan_mode(self): + """Return the fan speed set.""" + return self._current_fan_mode + + @property + def fan_list(self): + """List of available fan modes.""" + return self._fan_list + + @property + def current_swing_mode(self): + """Return the swing mode set.""" + return self._current_swing_mode + + @property + def swing_list(self): + """List of available swing modes.""" + return self._swing_list + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + unit = self._unit + if unit == 'C': + return TEMP_CELSIUS + elif unit == 'F': + return TEMP_FAHRENHEIT + else: + _LOGGER.exception("unit_of_measurement=%s is not valid", + unit) + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def current_operation(self): + """Return the current operation mode.""" + return self._current_operation + + @property + def operation_list(self): + """List of available operation modes.""" + return self._operation_list + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temperature + + def set_temperature(self, temperature): + """Set new target temperature.""" + for value in self._node.get_values( + class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): + if value.command_class != 67 and value.index != self._index: + continue + if self._zxt_120: + # ZXT-120 does not support get setpoint + self._target_temperature = temperature + if ZXT_120_SET_TEMP.get(self._current_operation) \ + != value.index: + continue + _LOGGER.debug("ZXT_120_SET_TEMP=%s and" + " self._current_operation=%s", + ZXT_120_SET_TEMP.get(self._current_operation), + self._current_operation) + # ZXT-120 responds only to whole int + value.data = int(round(temperature, 0)) + else: + value.data = int(temperature) + break + + 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: + 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: + value.data = bytes(operation_mode, 'utf-8') + break + + def set_swing_mode(self, swing_mode): + """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: + value.data = bytes(swing_mode, 'utf-8') + break diff --git a/homeassistant/components/ecobee.py b/homeassistant/components/ecobee.py index 470449b02cb..d684b903d0c 100644 --- a/homeassistant/components/ecobee.py +++ b/homeassistant/components/ecobee.py @@ -69,7 +69,7 @@ def setup_ecobee(hass, network, config): hold_temp = config[DOMAIN].get(HOLD_TEMP, False) - discovery.load_platform(hass, 'thermostat', DOMAIN, + discovery.load_platform(hass, 'climate', DOMAIN, {'hold_temp': hold_temp}, config) discovery.load_platform(hass, 'sensor', DOMAIN, {}, config) discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index 8568408f3ec..fe65929a346 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -28,7 +28,7 @@ DISCOVER_LIGHTS = 'homematic.light' DISCOVER_SENSORS = 'homematic.sensor' DISCOVER_BINARY_SENSORS = 'homematic.binary_sensor' DISCOVER_ROLLERSHUTTER = 'homematic.rollershutter' -DISCOVER_THERMOSTATS = 'homematic.thermostat' +DISCOVER_THERMOSTATS = 'homematic.climate' ATTR_DISCOVER_DEVICES = 'devices' ATTR_PARAM = 'param' @@ -214,7 +214,7 @@ def system_callback_handler(hass, config, src, *args): ('rollershutter', DISCOVER_ROLLERSHUTTER), ('binary_sensor', DISCOVER_BINARY_SENSORS), ('sensor', DISCOVER_SENSORS), - ('thermostat', DISCOVER_THERMOSTATS)): + ('climate', DISCOVER_THERMOSTATS)): # Get all devices of a specific type found_devices = _get_devices(discovery_type, key_dict) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index afccc043223..005add4e634 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -2,7 +2,7 @@ Support for Nest thermostats and protect smoke alarms. For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/thermostat.nest/ +https://home-assistant.io/components/climate.nest/ """ import logging import socket diff --git a/homeassistant/components/thermostat/zwave.py b/homeassistant/components/thermostat/zwave.py index d44e6b5f70a..6bed82284bb 100644 --- a/homeassistant/components/thermostat/zwave.py +++ b/homeassistant/components/thermostat/zwave.py @@ -57,6 +57,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): COMMAND_CLASS_THERMOSTAT_SETPOINT)): return + if value.command_class != COMMAND_CLASS_SENSOR_MULTILEVEL and \ + value.command_class != COMMAND_CLASS_THERMOSTAT_SETPOINT: + return + add_devices([ZWaveThermostat(value)]) _LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s", discovery_info, zwave.NETWORK) diff --git a/homeassistant/components/zwave.py b/homeassistant/components/zwave.py index a60319188ce..3e0db87664e 100644 --- a/homeassistant/components/zwave.py +++ b/homeassistant/components/zwave.py @@ -151,18 +151,6 @@ DISCOVERY_COMPONENTS = [ [COMMAND_CLASS_SENSOR_BINARY], TYPE_BOOL, GENRE_USER), - ('thermostat', - [GENERIC_COMMAND_CLASS_THERMOSTAT], - [SPECIFIC_DEVICE_CLASS_WHATEVER], - [COMMAND_CLASS_THERMOSTAT_SETPOINT], - TYPE_WHATEVER, - GENRE_WHATEVER), - ('hvac', - [GENERIC_COMMAND_CLASS_THERMOSTAT], - [SPECIFIC_DEVICE_CLASS_WHATEVER], - [COMMAND_CLASS_THERMOSTAT_FAN_MODE], - TYPE_WHATEVER, - GENRE_WHATEVER), ('lock', [GENERIC_COMMAND_CLASS_ENTRY_CONTROL], [SPECIFIC_DEVICE_CLASS_ADVANCED_DOOR_LOCK, @@ -186,7 +174,13 @@ DISCOVERY_COMPONENTS = [ [COMMAND_CLASS_SWITCH_BINARY, COMMAND_CLASS_BARRIER_OPERATOR], TYPE_BOOL, - GENRE_USER) + GENRE_USER), + ('climate', + [GENERIC_COMMAND_CLASS_THERMOSTAT], + [SPECIFIC_DEVICE_CLASS_WHATEVER], + [COMMAND_CLASS_THERMOSTAT_SETPOINT], + TYPE_WHATEVER, + GENRE_WHATEVER), ] diff --git a/requirements_all.txt b/requirements_all.txt index 0a210e55b98..94d610cdee1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -40,6 +40,7 @@ blinkstick==1.1.7 # homeassistant.components.sensor.bitcoin blockchain==1.3.3 +# homeassistant.components.climate.eq3btsmart # homeassistant.components.thermostat.eq3btsmart # bluepy_devices==0.2.0 @@ -67,6 +68,7 @@ eliqonline==1.0.12 # homeassistant.components.enocean enocean==0.31 +# homeassistant.components.climate.honeywell # homeassistant.components.thermostat.honeywell evohomeclient==0.2.5 @@ -103,6 +105,7 @@ ha-ffmpeg==0.4 # homeassistant.components.mqtt.server hbmqtt==0.7.1 +# homeassistant.components.climate.heatmiser # homeassistant.components.thermostat.heatmiser heatmiserV3==0.9.1 @@ -254,6 +257,7 @@ plexapi==2.0.2 # homeassistant.components.sensor.serial_pm pmsensor==0.2 +# homeassistant.components.climate.proliphix # homeassistant.components.thermostat.proliphix proliphix==0.3.1 @@ -388,6 +392,7 @@ pyvera==0.2.15 # homeassistant.components.wemo pywemo==0.4.5 +# homeassistant.components.climate.radiotherm # homeassistant.components.thermostat.radiotherm radiotherm==1.2 @@ -418,6 +423,7 @@ sleekxmpp==1.3.1 # homeassistant.components.media_player.snapcast snapcast==1.2.1 +# homeassistant.components.climate.honeywell # homeassistant.components.thermostat.honeywell somecomfort==0.2.1 diff --git a/tests/components/climate/__init__.py b/tests/components/climate/__init__.py new file mode 100644 index 00000000000..441c917cab7 --- /dev/null +++ b/tests/components/climate/__init__.py @@ -0,0 +1 @@ +"""The tests for climate component.""" diff --git a/tests/components/climate/test_demo.py b/tests/components/climate/test_demo.py new file mode 100644 index 00000000000..4dab359688c --- /dev/null +++ b/tests/components/climate/test_demo.py @@ -0,0 +1,166 @@ +"""The tests for the demo climate component.""" +import unittest + +from homeassistant.util.unit_system import ( + METRIC_SYSTEM, +) +from homeassistant.components import climate + +from tests.common import get_test_home_assistant + + +ENTITY_CLIMATE = 'climate.hvac' + + +class TestDemoClimate(unittest.TestCase): + """Test the demo climate hvac.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.units = METRIC_SYSTEM + self.assertTrue(climate.setup(self.hass, {'climate': { + 'platform': 'demo', + }})) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_setup_params(self): + """Test the inititial parameters.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(21, state.attributes.get('temperature')) + self.assertEqual('on', state.attributes.get('away_mode')) + self.assertEqual(22, state.attributes.get('current_temperature')) + self.assertEqual("On High", state.attributes.get('fan_mode')) + self.assertEqual(67, state.attributes.get('humidity')) + self.assertEqual(54, state.attributes.get('current_humidity')) + self.assertEqual("Off", state.attributes.get('swing_mode')) + self.assertEqual("Cool", state.attributes.get('operation_mode')) + self.assertEqual('off', state.attributes.get('aux_heat')) + + def test_default_setup_params(self): + """Test the setup with default parameters.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(7, state.attributes.get('min_temp')) + self.assertEqual(35, state.attributes.get('max_temp')) + self.assertEqual(30, state.attributes.get('min_humidity')) + self.assertEqual(99, state.attributes.get('max_humidity')) + + def test_set_target_temp_bad_attr(self): + """Test setting the target temperature without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(21, state.attributes.get('temperature')) + climate.set_temperature(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual(21, state.attributes.get('temperature')) + + def test_set_target_temp(self): + """Test the setting of the target temperature.""" + climate.set_temperature(self.hass, 30, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(30.0, state.attributes.get('temperature')) + + def test_set_target_humidity_bad_attr(self): + """Test setting the target humidity without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(67, state.attributes.get('humidity')) + climate.set_humidity(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual(67, state.attributes.get('humidity')) + + def test_set_target_humidity(self): + """Test the setting of the target humidity.""" + climate.set_humidity(self.hass, 64, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(64.0, state.attributes.get('humidity')) + + def test_set_fan_mode_bad_attr(self): + """Test setting fan mode without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("On High", state.attributes.get('fan_mode')) + climate.set_fan_mode(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual("On High", state.attributes.get('fan_mode')) + + def test_set_fan_mode(self): + """Test setting of new fan mode.""" + climate.set_fan_mode(self.hass, "On Low", ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("On Low", state.attributes.get('fan_mode')) + + def test_set_swing_mode_bad_attr(self): + """Test setting swing mode without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("Off", state.attributes.get('swing_mode')) + climate.set_swing_mode(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual("Off", state.attributes.get('swing_mode')) + + def test_set_swing(self): + """Test setting of new swing mode.""" + climate.set_swing_mode(self.hass, "Auto", ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("Auto", state.attributes.get('swing_mode')) + + def test_set_operation_bad_attr(self): + """Test setting operation mode without required attribute.""" + self.assertEqual("Cool", self.hass.states.get(ENTITY_CLIMATE).state) + climate.set_operation_mode(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual("Cool", self.hass.states.get(ENTITY_CLIMATE).state) + + def test_set_operation(self): + """Test setting of new operation mode.""" + climate.set_operation_mode(self.hass, "Heat", ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual("Heat", self.hass.states.get(ENTITY_CLIMATE).state) + + def test_set_away_mode_bad_attr(self): + """Test setting the away mode without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('on', state.attributes.get('away_mode')) + climate.set_away_mode(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual('on', state.attributes.get('away_mode')) + + def test_set_away_mode_on(self): + """Test setting the away mode on/true.""" + climate.set_away_mode(self.hass, True, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('on', state.attributes.get('away_mode')) + + def test_set_away_mode_off(self): + """Test setting the away mode off/false.""" + climate.set_away_mode(self.hass, False, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('off', state.attributes.get('away_mode')) + + def test_set_aux_heat_bad_attr(self): + """Test setting the auxillary heater without required attribute.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('off', state.attributes.get('aux_heat')) + climate.set_aux_heat(self.hass, None, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + self.assertEqual('off', state.attributes.get('aux_heat')) + + def test_set_aux_heat_on(self): + """Test setting the axillary heater on/true.""" + climate.set_aux_heat(self.hass, True, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('on', state.attributes.get('aux_heat')) + + def test_set_aux_heat_off(self): + """Test setting the auxillary heater off/false.""" + climate.set_aux_heat(self.hass, False, ENTITY_CLIMATE) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual('off', state.attributes.get('aux_heat')) diff --git a/tests/components/climate/test_generic_thermostat.py b/tests/components/climate/test_generic_thermostat.py new file mode 100644 index 00000000000..5c03abdf90f --- /dev/null +++ b/tests/components/climate/test_generic_thermostat.py @@ -0,0 +1,493 @@ +"""The tests for the generic_thermostat.""" +import datetime +import unittest +from unittest import mock + + +from homeassistant.bootstrap import _setup_component +from homeassistant.const import ( + ATTR_UNIT_OF_MEASUREMENT, + SERVICE_TURN_OFF, + SERVICE_TURN_ON, + STATE_ON, + STATE_OFF, + TEMP_CELSIUS, +) +from homeassistant.util.unit_system import METRIC_SYSTEM +from homeassistant.components import climate + +from tests.common import get_test_home_assistant + + +ENTITY = 'climate.test' +ENT_SENSOR = 'sensor.test' +ENT_SWITCH = 'switch.test' +MIN_TEMP = 3.0 +MAX_TEMP = 65.0 +TARGET_TEMP = 42.0 + + +class TestSetupClimateGenericThermostat(unittest.TestCase): + """Test the Generic thermostat with custom config.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_setup_missing_conf(self): + """Test set up heat_control with missing config values.""" + config = { + 'name': 'test', + 'target_sensor': ENT_SENSOR + } + self.assertFalse(_setup_component(self.hass, 'climate', { + 'climate': config})) + + def test_valid_conf(self): + """Test set up genreic_thermostat with valid config values.""" + self.assertTrue(_setup_component(self.hass, 'climate', + {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR}})) + + def test_setup_with_sensor(self): + """Test set up heat_control with sensor to trigger update at init.""" + self.hass.states.set(ENT_SENSOR, 22.0, { + ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS + }) + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR + }}) + state = self.hass.states.get(ENTITY) + self.assertEqual( + TEMP_CELSIUS, state.attributes.get('unit_of_measurement')) + self.assertEqual(22.0, state.attributes.get('current_temperature')) + + +class TestClimateGenericThermostat(unittest.TestCase): + """Test the Generic thermostat.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.units = METRIC_SYSTEM + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR + }}) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_setup_defaults_to_unknown(self): + """Test the setting of defaults to unknown.""" + self.assertEqual('unknown', self.hass.states.get(ENTITY).state) + + def test_default_setup_params(self): + """Test the setup with default parameters.""" + state = self.hass.states.get(ENTITY) + self.assertEqual(7, state.attributes.get('min_temp')) + self.assertEqual(35, state.attributes.get('max_temp')) + self.assertEqual(None, state.attributes.get('temperature')) + + def test_custom_setup_params(self): + """Test the setup with custom parameters.""" + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR, + 'min_temp': MIN_TEMP, + 'max_temp': MAX_TEMP, + 'target_temp': TARGET_TEMP + }}) + state = self.hass.states.get(ENTITY) + self.assertEqual(MIN_TEMP, state.attributes.get('min_temp')) + self.assertEqual(MAX_TEMP, state.attributes.get('max_temp')) + self.assertEqual(TARGET_TEMP, state.attributes.get('temperature')) + + def test_set_target_temp(self): + """Test the setting of the target temperature.""" + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY) + self.assertEqual(30.0, state.attributes.get('temperature')) + + def test_sensor_bad_unit(self): + """Test sensor that have bad unit.""" + state = self.hass.states.get(ENTITY) + temp = state.attributes.get('current_temperature') + unit = state.attributes.get('unit_of_measurement') + + self._setup_sensor(22.0, unit='bad_unit') + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY) + self.assertEqual(unit, state.attributes.get('unit_of_measurement')) + self.assertEqual(temp, state.attributes.get('current_temperature')) + + def test_sensor_bad_value(self): + """Test sensor that have None as state.""" + state = self.hass.states.get(ENTITY) + temp = state.attributes.get('current_temperature') + unit = state.attributes.get('unit_of_measurement') + + self._setup_sensor(None) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY) + self.assertEqual(unit, state.attributes.get('unit_of_measurement')) + self.assertEqual(temp, state.attributes.get('current_temperature')) + + def test_set_target_temp_heater_on(self): + """Test if target temperature turn heater on.""" + self._setup_switch(False) + self._setup_sensor(25) + self.hass.pool.block_till_done() + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_set_target_temp_heater_off(self): + """Test if target temperature turn heater off.""" + self._setup_switch(True) + self._setup_sensor(30) + self.hass.pool.block_till_done() + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_set_temp_change_heater_on(self): + """Test if temperature change turn heater on.""" + self._setup_switch(False) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_temp_change_heater_off(self): + """Test if temperature change turn heater off.""" + self._setup_switch(True) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + """Setup the test sensor.""" + self.hass.states.set(ENT_SENSOR, temp, { + ATTR_UNIT_OF_MEASUREMENT: unit + }) + + def _setup_switch(self, is_on): + """Setup the test switch.""" + self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF) + self.calls = [] + + def log_call(call): + """Log service calls.""" + self.calls.append(call) + + self.hass.services.register('switch', SERVICE_TURN_ON, log_call) + self.hass.services.register('switch', SERVICE_TURN_OFF, log_call) + + +class TestClimateGenericThermostatACMode(unittest.TestCase): + """Test the Generic thermostat.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.temperature_unit = TEMP_CELSIUS + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR, + 'ac_mode': True + }}) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_set_target_temp_ac_off(self): + """Test if target temperature turn ac off.""" + self._setup_switch(True) + self._setup_sensor(25) + self.hass.pool.block_till_done() + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_set_target_temp_ac_on(self): + """Test if target temperature turn ac on.""" + self._setup_switch(False) + self._setup_sensor(30) + self.hass.pool.block_till_done() + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_set_temp_change_ac_off(self): + """Test if temperature change turn ac off.""" + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_temp_change_ac_on(self): + """Test if temperature change turn ac on.""" + self._setup_switch(False) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + """Setup the test sensor.""" + self.hass.states.set(ENT_SENSOR, temp, { + ATTR_UNIT_OF_MEASUREMENT: unit + }) + + def _setup_switch(self, is_on): + """Setup the test switch.""" + self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF) + self.calls = [] + + def log_call(call): + """Log service calls.""" + self.calls.append(call) + + self.hass.services.register('switch', SERVICE_TURN_ON, log_call) + self.hass.services.register('switch', SERVICE_TURN_OFF, log_call) + + +class TestClimateGenericThermostatACModeMinCycle(unittest.TestCase): + """Test the Generic Thermostat.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.temperature_unit = TEMP_CELSIUS + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR, + 'ac_mode': True, + 'min_cycle_duration': datetime.timedelta(minutes=10) + }}) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_temp_change_ac_trigger_on_not_long_enough(self): + """Test if temperature change turn ac on.""" + self._setup_switch(False) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_ac_trigger_on_long_enough(self): + """Test if temperature change turn ac on.""" + fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, + tzinfo=datetime.timezone.utc) + with mock.patch('homeassistant.helpers.condition.dt_util.utcnow', + return_value=fake_changed): + self._setup_switch(False) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_temp_change_ac_trigger_off_not_long_enough(self): + """Test if temperature change turn ac on.""" + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_ac_trigger_off_long_enough(self): + """Test if temperature change turn ac on.""" + fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, + tzinfo=datetime.timezone.utc) + with mock.patch('homeassistant.helpers.condition.dt_util.utcnow', + return_value=fake_changed): + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + """Setup the test sensor.""" + self.hass.states.set(ENT_SENSOR, temp, { + ATTR_UNIT_OF_MEASUREMENT: unit + }) + + def _setup_switch(self, is_on): + """Setup the test switch.""" + self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF) + self.calls = [] + + def log_call(call): + """Log service calls.""" + self.calls.append(call) + + self.hass.services.register('switch', SERVICE_TURN_ON, log_call) + self.hass.services.register('switch', SERVICE_TURN_OFF, log_call) + + +class TestClimateGenericThermostatMinCycle(unittest.TestCase): + """Test the Generic thermostat.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.config.temperature_unit = TEMP_CELSIUS + climate.setup(self.hass, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR, + 'min_cycle_duration': datetime.timedelta(minutes=10) + }}) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_temp_change_heater_trigger_off_not_long_enough(self): + """Test if temp change doesn't turn heater off because of time.""" + self._setup_switch(True) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_heater_trigger_on_not_long_enough(self): + """Test if temp change doesn't turn heater on because of time.""" + self._setup_switch(False) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_heater_trigger_on_long_enough(self): + """Test if temperature change turn heater on after min cycle.""" + fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, + tzinfo=datetime.timezone.utc) + with mock.patch('homeassistant.helpers.condition.dt_util.utcnow', + return_value=fake_changed): + self._setup_switch(False) + climate.set_temperature(self.hass, 30) + self.hass.pool.block_till_done() + self._setup_sensor(25) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_ON, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def test_temp_change_heater_trigger_off_long_enough(self): + """Test if temperature change turn heater off after min cycle.""" + fake_changed = datetime.datetime(1918, 11, 11, 11, 11, 11, + tzinfo=datetime.timezone.utc) + with mock.patch('homeassistant.helpers.condition.dt_util.utcnow', + return_value=fake_changed): + self._setup_switch(True) + climate.set_temperature(self.hass, 25) + self.hass.pool.block_till_done() + self._setup_sensor(30) + self.hass.pool.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + + def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + """Setup the test sensor.""" + self.hass.states.set(ENT_SENSOR, temp, { + ATTR_UNIT_OF_MEASUREMENT: unit + }) + + def _setup_switch(self, is_on): + """Setup the test switch.""" + self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF) + self.calls = [] + + def log_call(call): + """Log service calls.""" + self.calls.append(call) + + self.hass.services.register('switch', SERVICE_TURN_ON, log_call) + self.hass.services.register('switch', SERVICE_TURN_OFF, log_call) diff --git a/tests/components/climate/test_honeywell.py b/tests/components/climate/test_honeywell.py new file mode 100644 index 00000000000..6c97b65dea7 --- /dev/null +++ b/tests/components/climate/test_honeywell.py @@ -0,0 +1,377 @@ +"""The test the Honeywell thermostat module.""" +import socket +import unittest +from unittest import mock + +import somecomfort + +from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, + TEMP_CELSIUS, TEMP_FAHRENHEIT) +import homeassistant.components.climate.honeywell as honeywell + + +class TestHoneywell(unittest.TestCase): + """A test class for Honeywell themostats.""" + + @mock.patch('somecomfort.SomeComfort') + @mock.patch('homeassistant.components.climate.' + 'honeywell.HoneywellUSThermostat') + def test_setup_us(self, mock_ht, mock_sc): + """Test for the US setup.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + 'region': 'us', + } + bad_pass_config = { + CONF_USERNAME: 'user', + 'region': 'us', + } + bad_region_config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + 'region': 'un', + } + hass = mock.MagicMock() + add_devices = mock.MagicMock() + + locations = [ + mock.MagicMock(), + mock.MagicMock(), + ] + devices_1 = [mock.MagicMock()] + devices_2 = [mock.MagicMock(), mock.MagicMock] + mock_sc.return_value.locations_by_id.values.return_value = \ + locations + locations[0].devices_by_id.values.return_value = devices_1 + locations[1].devices_by_id.values.return_value = devices_2 + + result = honeywell.setup_platform(hass, bad_pass_config, add_devices) + self.assertFalse(result) + result = honeywell.setup_platform(hass, bad_region_config, add_devices) + self.assertFalse(result) + result = honeywell.setup_platform(hass, config, add_devices) + self.assertTrue(result) + mock_sc.assert_called_once_with('user', 'pass') + mock_ht.assert_has_calls([ + mock.call(mock_sc.return_value, devices_1[0]), + mock.call(mock_sc.return_value, devices_2[0]), + mock.call(mock_sc.return_value, devices_2[1]), + ]) + + @mock.patch('somecomfort.SomeComfort') + def test_setup_us_failures(self, mock_sc): + """Test the US setup.""" + hass = mock.MagicMock() + add_devices = mock.MagicMock() + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + 'region': 'us', + } + + mock_sc.side_effect = somecomfort.AuthError + result = honeywell.setup_platform(hass, config, add_devices) + self.assertFalse(result) + self.assertFalse(add_devices.called) + + mock_sc.side_effect = somecomfort.SomeComfortError + result = honeywell.setup_platform(hass, config, add_devices) + self.assertFalse(result) + self.assertFalse(add_devices.called) + + @mock.patch('somecomfort.SomeComfort') + @mock.patch('homeassistant.components.climate.' + 'honeywell.HoneywellUSThermostat') + def _test_us_filtered_devices(self, mock_ht, mock_sc, loc=None, dev=None): + """Test for US filtered thermostats.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + 'region': 'us', + 'location': loc, + 'thermostat': dev, + } + locations = { + 1: mock.MagicMock(locationid=mock.sentinel.loc1, + devices_by_id={ + 11: mock.MagicMock( + deviceid=mock.sentinel.loc1dev1), + 12: mock.MagicMock( + deviceid=mock.sentinel.loc1dev2), + }), + 2: mock.MagicMock(locationid=mock.sentinel.loc2, + devices_by_id={ + 21: mock.MagicMock( + deviceid=mock.sentinel.loc2dev1), + }), + 3: mock.MagicMock(locationid=mock.sentinel.loc3, + devices_by_id={ + 31: mock.MagicMock( + deviceid=mock.sentinel.loc3dev1), + }), + } + mock_sc.return_value = mock.MagicMock(locations_by_id=locations) + hass = mock.MagicMock() + add_devices = mock.MagicMock() + self.assertEqual(True, + honeywell.setup_platform(hass, config, add_devices)) + + return mock_ht.call_args_list, mock_sc + + def test_us_filtered_thermostat_1(self): + """Test for US filtered thermostats.""" + result, client = self._test_us_filtered_devices( + dev=mock.sentinel.loc1dev1) + devices = [x[0][1].deviceid for x in result] + self.assertEqual([mock.sentinel.loc1dev1], devices) + + def test_us_filtered_thermostat_2(self): + """Test for US filtered location.""" + result, client = self._test_us_filtered_devices( + dev=mock.sentinel.loc2dev1) + devices = [x[0][1].deviceid for x in result] + self.assertEqual([mock.sentinel.loc2dev1], devices) + + def test_us_filtered_location_1(self): + """Test for US filtered locations.""" + result, client = self._test_us_filtered_devices( + loc=mock.sentinel.loc1) + devices = [x[0][1].deviceid for x in result] + self.assertEqual([mock.sentinel.loc1dev1, + mock.sentinel.loc1dev2], devices) + + def test_us_filtered_location_2(self): + """Test for US filtered locations.""" + result, client = self._test_us_filtered_devices( + loc=mock.sentinel.loc2) + devices = [x[0][1].deviceid for x in result] + self.assertEqual([mock.sentinel.loc2dev1], devices) + + @mock.patch('evohomeclient.EvohomeClient') + @mock.patch('homeassistant.components.climate.honeywell.' + 'RoundThermostat') + def test_eu_setup_full_config(self, mock_round, mock_evo): + """Test the EU setup wwith complete configuration.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + honeywell.CONF_AWAY_TEMP: 20, + 'region': 'eu', + } + mock_evo.return_value.temperatures.return_value = [ + {'id': 'foo'}, {'id': 'bar'}] + hass = mock.MagicMock() + add_devices = mock.MagicMock() + self.assertTrue(honeywell.setup_platform(hass, config, add_devices)) + mock_evo.assert_called_once_with('user', 'pass') + mock_evo.return_value.temperatures.assert_called_once_with( + force_refresh=True) + mock_round.assert_has_calls([ + mock.call(mock_evo.return_value, 'foo', True, 20), + mock.call(mock_evo.return_value, 'bar', False, 20), + ]) + self.assertEqual(2, add_devices.call_count) + + @mock.patch('evohomeclient.EvohomeClient') + @mock.patch('homeassistant.components.climate.honeywell.' + 'RoundThermostat') + def test_eu_setup_partial_config(self, mock_round, mock_evo): + """Test the EU setup with partial configuration.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + 'region': 'eu', + } + mock_evo.return_value.temperatures.return_value = [ + {'id': 'foo'}, {'id': 'bar'}] + hass = mock.MagicMock() + add_devices = mock.MagicMock() + self.assertTrue(honeywell.setup_platform(hass, config, add_devices)) + default = honeywell.DEFAULT_AWAY_TEMP + mock_round.assert_has_calls([ + mock.call(mock_evo.return_value, 'foo', True, default), + mock.call(mock_evo.return_value, 'bar', False, default), + ]) + + @mock.patch('evohomeclient.EvohomeClient') + @mock.patch('homeassistant.components.climate.honeywell.' + 'RoundThermostat') + def test_eu_setup_bad_temp(self, mock_round, mock_evo): + """Test the EU setup with invalid temperature.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + honeywell.CONF_AWAY_TEMP: 'ponies', + 'region': 'eu', + } + self.assertFalse(honeywell.setup_platform(None, config, None)) + + @mock.patch('evohomeclient.EvohomeClient') + @mock.patch('homeassistant.components.climate.honeywell.' + 'RoundThermostat') + def test_eu_setup_error(self, mock_round, mock_evo): + """Test the EU setup with errors.""" + config = { + CONF_USERNAME: 'user', + CONF_PASSWORD: 'pass', + honeywell.CONF_AWAY_TEMP: 20, + 'region': 'eu', + } + mock_evo.return_value.temperatures.side_effect = socket.error + add_devices = mock.MagicMock() + hass = mock.MagicMock() + self.assertFalse(honeywell.setup_platform(hass, config, add_devices)) + + +class TestHoneywellRound(unittest.TestCase): + """A test class for Honeywell Round thermostats.""" + + def setup_method(self, method): + """Test the setup method.""" + def fake_temperatures(force_refresh=None): + """Create fake temperatures.""" + temps = [ + {'id': '1', 'temp': 20, 'setpoint': 21, + 'thermostat': 'main', 'name': 'House'}, + {'id': '2', 'temp': 21, 'setpoint': 22, + 'thermostat': 'DOMESTIC_HOT_WATER'}, + ] + return temps + + self.device = mock.MagicMock() + self.device.temperatures.side_effect = fake_temperatures + self.round1 = honeywell.RoundThermostat(self.device, '1', + True, 16) + self.round2 = honeywell.RoundThermostat(self.device, '2', + False, 17) + + def test_attributes(self): + """Test the attributes.""" + self.assertEqual('House', self.round1.name) + self.assertEqual(TEMP_CELSIUS, self.round1.unit_of_measurement) + self.assertEqual(20, self.round1.current_temperature) + self.assertEqual(21, self.round1.target_temperature) + self.assertFalse(self.round1.is_away_mode_on) + + self.assertEqual('Hot Water', self.round2.name) + self.assertEqual(TEMP_CELSIUS, self.round2.unit_of_measurement) + self.assertEqual(21, self.round2.current_temperature) + self.assertEqual(None, self.round2.target_temperature) + self.assertFalse(self.round2.is_away_mode_on) + + def test_away_mode(self): + """Test setting the away mode.""" + self.assertFalse(self.round1.is_away_mode_on) + self.round1.turn_away_mode_on() + self.assertTrue(self.round1.is_away_mode_on) + self.device.set_temperature.assert_called_once_with('House', 16) + + self.device.set_temperature.reset_mock() + self.round1.turn_away_mode_off() + self.assertFalse(self.round1.is_away_mode_on) + self.device.cancel_temp_override.assert_called_once_with('House') + + def test_set_temperature(self): + """Test setting the temperature.""" + self.round1.set_temperature(25) + self.device.set_temperature.assert_called_once_with('House', 25) + + def test_set_operation_mode(self: unittest.TestCase) -> None: + """Test setting the system operation.""" + self.round1.set_operation_mode('cool') + self.assertEqual('cool', self.round1.current_operation) + self.assertEqual('cool', self.device.system_mode) + + self.round1.set_operation_mode('heat') + self.assertEqual('heat', self.round1.current_operation) + self.assertEqual('heat', self.device.system_mode) + + +class TestHoneywellUS(unittest.TestCase): + """A test class for Honeywell US thermostats.""" + + def setup_method(self, method): + """Test the setup method.""" + self.client = mock.MagicMock() + self.device = mock.MagicMock() + self.honeywell = honeywell.HoneywellUSThermostat( + self.client, self.device) + + self.device.fan_running = True + self.device.name = 'test' + self.device.temperature_unit = 'F' + self.device.current_temperature = 72 + self.device.setpoint_cool = 78 + self.device.setpoint_heat = 65 + self.device.system_mode = 'heat' + self.device.fan_mode = 'auto' + + def test_properties(self): + """Test the properties.""" + self.assertTrue(self.honeywell.is_fan_on) + self.assertEqual('test', self.honeywell.name) + self.assertEqual(72, self.honeywell.current_temperature) + + def test_unit_of_measurement(self): + """Test the unit of measurement.""" + self.assertEqual(TEMP_FAHRENHEIT, self.honeywell.unit_of_measurement) + self.device.temperature_unit = 'C' + self.assertEqual(TEMP_CELSIUS, self.honeywell.unit_of_measurement) + + def test_target_temp(self): + """Test the target temperature.""" + self.assertEqual(65, self.honeywell.target_temperature) + self.device.system_mode = 'cool' + self.assertEqual(78, self.honeywell.target_temperature) + + def test_set_temp(self): + """Test setting the temperature.""" + self.honeywell.set_temperature(70) + self.assertEqual(70, self.device.setpoint_heat) + self.assertEqual(70, self.honeywell.target_temperature) + + self.device.system_mode = 'cool' + self.assertEqual(78, self.honeywell.target_temperature) + self.honeywell.set_temperature(74) + self.assertEqual(74, self.device.setpoint_cool) + self.assertEqual(74, self.honeywell.target_temperature) + + def test_set_operation_mode(self: unittest.TestCase) -> None: + """Test setting the operation mode.""" + self.honeywell.set_operation_mode('cool') + self.assertEqual('cool', self.honeywell.current_operation) + self.assertEqual('cool', self.device.system_mode) + + self.honeywell.set_operation_mode('heat') + self.assertEqual('heat', self.honeywell.current_operation) + self.assertEqual('heat', self.device.system_mode) + + def test_set_temp_fail(self): + """Test if setting the temperature fails.""" + self.device.setpoint_heat = mock.MagicMock( + side_effect=somecomfort.SomeComfortError) + self.honeywell.set_temperature(123) + + def test_attributes(self): + """Test the attributes.""" + expected = { + 'fan': 'running', + 'fanmode': 'auto', + 'system_mode': 'heat', + } + self.assertEqual(expected, self.honeywell.device_state_attributes) + expected['fan'] = 'idle' + self.device.fan_running = False + self.assertEqual(expected, self.honeywell.device_state_attributes) + + def test_with_no_fan(self): + """Test if there is on fan.""" + self.device.fan_running = False + self.device.fan_mode = None + expected = { + 'fan': 'idle', + 'fanmode': None, + 'system_mode': 'heat', + } + self.assertEqual(expected, self.honeywell.device_state_attributes) From c74e167a7be230f1ae56ad72ee47c2ef1c0100b5 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 19 Aug 2016 09:18:45 +0200 Subject: [PATCH 093/193] Use voluptuous for dweet, transmission, and twitch sensor (#2802) * Use voluptuous for dweet, transmission, and twitch sensor * Extent platform, ordering, and consts * Clean-up --- homeassistant/components/sensor/dweet.py | 34 ++++++----- .../components/sensor/transmission.py | 58 +++++++++++------- homeassistant/components/sensor/twitch.py | 22 +++++-- .../components/switch/transmission.py | 61 ++++++++++--------- homeassistant/const.py | 1 + 5 files changed, 107 insertions(+), 69 deletions(-) diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py index 9b078e9df74..503308ffb6f 100644 --- a/homeassistant/components/sensor/dweet.py +++ b/homeassistant/components/sensor/dweet.py @@ -8,16 +8,29 @@ import json import logging from datetime import timedelta -from homeassistant.const import CONF_VALUE_TEMPLATE, STATE_UNKNOWN +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_NAME, CONF_VALUE_TEMPLATE, STATE_UNKNOWN, CONF_UNIT_OF_MEASUREMENT) +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.helpers import template from homeassistant.util import Throttle -_LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['dweepy==0.2.0'] -DEFAULT_NAME = 'Dweet.io Sensor' CONF_DEVICE = 'device' +DEFAULT_NAME = 'Dweet.io Sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICE): cv.string, + vol.Required(CONF_VALUE_TEMPLATE): cv.template, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) @@ -28,13 +41,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Dweet sensor.""" import dweepy - device = config.get('device') + name = config.get(CONF_NAME) + device = config.get(CONF_DEVICE) value_template = config.get(CONF_VALUE_TEMPLATE) - - if None in (device, value_template): - _LOGGER.error('Not all required config keys present: %s', - ', '.join(CONF_DEVICE, CONF_VALUE_TEMPLATE)) - return False + unit = config.get(CONF_UNIT_OF_MEASUREMENT) try: content = json.dumps(dweepy.get_latest_dweet_for(device)[0]['content']) @@ -50,11 +60,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): dweet = DweetData(device) - add_devices([DweetSensor(hass, - dweet, - config.get('name', DEFAULT_NAME), - value_template, - config.get('unit_of_measurement'))]) + add_devices([DweetSensor(hass, dweet, name, value_template, unit)]) # pylint: disable=too-many-arguments diff --git a/homeassistant/components/sensor/transmission.py b/homeassistant/components/sensor/transmission.py index 46a2e607dbe..e5ce3da235c 100644 --- a/homeassistant/components/sensor/transmission.py +++ b/homeassistant/components/sensor/transmission.py @@ -7,17 +7,37 @@ https://home-assistant.io/components/sensor.transmission/ import logging from datetime import timedelta -from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_NAME, CONF_PORT, + CONF_MONITORED_VARIABLES, STATE_UNKNOWN, STATE_IDLE) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['transmissionrpc==0.11'] + +DEFAULT_NAME = 'Transmission' +DEFAULT_PORT = 9091 + SENSOR_TYPES = { 'current_status': ['Status', None], 'download_speed': ['Down Speed', 'MB/s'], 'upload_speed': ['Up Speed', 'MB/s'] } +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_MONITORED_VARIABLES, default=[]): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_USERNAME): cv.string, +}) + _LOGGER = logging.getLogger(__name__) _THROTTLED_REFRESH = None @@ -29,22 +49,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): import transmissionrpc from transmissionrpc.error import TransmissionError + name = config.get(CONF_NAME) host = config.get(CONF_HOST) - username = config.get(CONF_USERNAME, None) - password = config.get(CONF_PASSWORD, None) - port = config.get('port', 9091) - - name = config.get("name", "Transmission") - if not host: - _LOGGER.error('Missing config variable %s', CONF_HOST) - return False + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + port = config.get(CONF_PORT) transmission_api = transmissionrpc.Client( host, port=port, user=username, password=password) try: transmission_api.session_stats() except TransmissionError: - _LOGGER.exception("Connection to Transmission API failed.") + _LOGGER.exception("Connection to Transmission API failed") return False # pylint: disable=global-statement @@ -53,18 +69,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): transmission_api.session_stats) dev = [] - for variable in config['monitored_variables']: - if variable not in SENSOR_TYPES: - _LOGGER.error('Sensor type: "%s" does not exist', variable) - else: - dev.append(TransmissionSensor( - variable, transmission_api, name)) + for variable in config[CONF_MONITORED_VARIABLES]: + dev.append(TransmissionSensor(variable, transmission_api, name)) add_devices(dev) class TransmissionSensor(Entity): - """representation of a Transmission sensor.""" + """Representation of a Transmission sensor.""" def __init__(self, sensor_type, transmission_client, client_name): """Initialize the sensor.""" @@ -78,7 +90,7 @@ class TransmissionSensor(Entity): @property def name(self): """Return the name of the sensor.""" - return self.client_name + ' ' + self._name + return '{} {}'.format(self.client_name, self._name) @property def state(self): @@ -90,6 +102,7 @@ class TransmissionSensor(Entity): """Return the unit of measurement of this entity, if any.""" return self._unit_of_measurement + # pylint: disable=no-self-use def refresh_transmission_data(self): """Call the throttled Transmission refresh method.""" from transmissionrpc.error import TransmissionError @@ -98,13 +111,12 @@ class TransmissionSensor(Entity): try: _THROTTLED_REFRESH() except TransmissionError: - _LOGGER.exception( - self.name + " Connection to Transmission API failed." - ) + _LOGGER.error("Connection to Transmission API failed") def update(self): """Get the latest data from Transmission and updates the state.""" self.refresh_transmission_data() + if self.type == 'current_status': if self.transmission_client.session: upload = self.transmission_client.session.uploadSpeed @@ -116,9 +128,9 @@ class TransmissionSensor(Entity): elif upload == 0 and download > 0: self._state = 'Downloading' else: - self._state = 'Idle' + self._state = STATE_IDLE else: - self._state = 'Unknown' + self._state = STATE_UNKNOWN if self.transmission_client.session: if self.type == 'download_speed': diff --git a/homeassistant/components/sensor/twitch.py b/homeassistant/components/sensor/twitch.py index 7b18408105d..87bacbdafeb 100644 --- a/homeassistant/components/sensor/twitch.py +++ b/homeassistant/components/sensor/twitch.py @@ -4,8 +4,15 @@ Support for the Twitch stream status. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.twitch/ """ -from homeassistant.helpers.entity import Entity +import logging +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv + +CONF_CHANNELS = 'channels' STATE_STREAMING = 'streaming' STATE_OFFLINE = 'offline' ATTR_GAME = 'game' @@ -13,14 +20,21 @@ ATTR_TITLE = 'title' ICON = 'mdi:twitch' REQUIREMENTS = ['python-twitch==1.3.0'] -DOMAIN = 'twitch' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_CHANNELS, default=[]): + vol.All(cv.ensure_list, [cv.string]), +}) + +_LOGGER = logging.getLogger(__name__) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Twitch platform.""" - add_devices( - [TwitchSensor(channel) for channel in config.get('channels', [])]) + channels = config.get(CONF_CHANNELS, []) + + add_devices([TwitchSensor(channel) for channel in channels]) class TwitchSensor(Entity): diff --git a/homeassistant/components/switch/transmission.py b/homeassistant/components/switch/transmission.py index 10ebc7606a0..0771724e0a3 100644 --- a/homeassistant/components/switch/transmission.py +++ b/homeassistant/components/switch/transmission.py @@ -6,48 +6,56 @@ https://home-assistant.io/components/switch.transmission/ """ import logging +import voluptuous as vol + +from homeassistant.components.switch import PLATFORM_SCHEMA from homeassistant.const import ( - CONF_HOST, CONF_PASSWORD, CONF_USERNAME, STATE_OFF, STATE_ON) + CONF_HOST, CONF_NAME, CONF_PORT, CONF_PASSWORD, CONF_USERNAME, STATE_OFF, + STATE_ON) from homeassistant.helpers.entity import ToggleEntity +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['transmissionrpc==0.11'] + +DEFAULT_NAME = 'Transmission Turtle Mode' +DEFAULT_PORT = 9091 + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_USERNAME): cv.string, +}) _LOGGING = logging.getLogger(__name__) -REQUIREMENTS = ['transmissionrpc==0.11'] # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): - """Setup the transmission sensor.""" +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Transmission switch.""" import transmissionrpc from transmissionrpc.error import TransmissionError + name = config.get(CONF_NAME) host = config.get(CONF_HOST) - username = config.get(CONF_USERNAME, None) - password = config.get(CONF_PASSWORD, None) - port = config.get('port', 9091) - - name = config.get("name", "Transmission Turtle Mode") - if not host: - _LOGGING.error('Missing config variable %s', CONF_HOST) - return False - - # import logging - # logging.getLogger('transmissionrpc').setLevel(logging.DEBUG) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + port = config.get(CONF_PORT) transmission_api = transmissionrpc.Client( host, port=port, user=username, password=password) try: transmission_api.session_stats() except TransmissionError: - _LOGGING.exception("Connection to Transmission API failed.") + _LOGGING.error("Connection to Transmission API failed") return False - add_devices_callback([ - TransmissionSwitch(transmission_api, name) - ]) + add_devices([TransmissionSwitch(transmission_api, name)]) class TransmissionSwitch(ToggleEntity): - """Representation of a Transmission sensor.""" + """Representation of a Transmission switch.""" def __init__(self, transmission_client, name): """Initialize the Transmission switch.""" @@ -77,18 +85,15 @@ class TransmissionSwitch(ToggleEntity): def turn_on(self, **kwargs): """Turn the device on.""" - _LOGGING.info("Turning on Turtle Mode") - self.transmission_client.set_session( - alt_speed_enabled=True) + _LOGGING.debug("Turning Turtle Mode of Transmission on") + self.transmission_client.set_session(alt_speed_enabled=True) def turn_off(self, **kwargs): """Turn the device off.""" - _LOGGING.info("Turning off Turtle Mode ") - self.transmission_client.set_session( - alt_speed_enabled=False) + _LOGGING.debug("Turning Turtle Mode of Transmission off") + self.transmission_client.set_session(alt_speed_enabled=False) def update(self): """Get the latest data from Transmission and updates the state.""" - active = self.transmission_client.get_session( - ).alt_speed_enabled + active = self.transmission_client.get_session().alt_speed_enabled self._state = STATE_ON if active else STATE_OFF diff --git a/homeassistant/const.py b/homeassistant/const.py index 52d71d141ac..10ddcc2f7cc 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -55,6 +55,7 @@ CONF_STATE = 'state' CONF_TEMPERATURE_UNIT = 'temperature_unit' CONF_TIME_ZONE = 'time_zone' CONF_TRIGGER_TIME = 'trigger_time' +CONF_UNIT_OF_MEASUREMENT = 'unit_of_measurement' CONF_UNIT_SYSTEM = 'unit_system' CONF_USERNAME = 'username' CONF_VALUE_TEMPLATE = 'value_template' From ca1de9cac1bd4e000744207a3e0ad823103f2043 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 19 Aug 2016 13:41:01 +0200 Subject: [PATCH 094/193] Add url to validation (#2874) * Add url to validation * Fix pylint issue * Clean-up --- homeassistant/helpers/config_validation.py | 12 ++++++++++++ tests/helpers/test_config_validation.py | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index ff1f694151f..d9c761832dc 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -1,5 +1,6 @@ """Helpers for config validation using voluptuous.""" from datetime import timedelta +from urllib.parse import urlparse from typing import Any, Union, TypeVar, Callable, Sequence, List, Dict @@ -255,6 +256,17 @@ def time_zone(value): weekdays = vol.All(ensure_list, [vol.In(WEEKDAYS)]) +# pylint: disable=no-value-for-parameter +def url(value: Any) -> str: + """Validate an URL.""" + url_in = str(value) + + if urlparse(url_in).scheme in ['http', 'https']: + return vol.Schema(vol.Url())(url_in) + + raise vol.Invalid('invalid url') + + # Validator helpers def key_dependency(key, dependency): diff --git a/tests/helpers/test_config_validation.py b/tests/helpers/test_config_validation.py index 3a72ef1da37..14d80d9104d 100644 --- a/tests/helpers/test_config_validation.py +++ b/tests/helpers/test_config_validation.py @@ -48,10 +48,10 @@ def test_longitude(): def test_port(): - """Test tcp/udp network port.""" + """Test TCP/UDP network port.""" schema = vol.Schema(cv.port) - for value in('invalid', None, -1, 0, 80000, '81000'): + for value in ('invalid', None, -1, 0, 80000, '81000'): with pytest.raises(vol.MultipleInvalid): schema(value) @@ -59,6 +59,21 @@ def test_port(): schema(value) +def test_url(): + """Test URL.""" + schema = vol.Schema(cv.url) + + for value in ('invalid', None, 100, 'htp://ha.io', 'http//ha.io', + 'http://??,**', 'https://??,**'): + with pytest.raises(vol.MultipleInvalid): + schema(value) + + for value in ('http://localhost', 'https://localhost/test/index.html', + 'http://home-assistant.io', 'http://home-assistant.io/test/', + 'https://community.home-assistant.io/'): + assert schema(value) + + def test_platform_config(): """Test platform config validation.""" for value in ( From def9bbf8275997900b1bf91ea6f609905cd16ce7 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Fri, 19 Aug 2016 14:56:10 +0200 Subject: [PATCH 095/193] Upgrade pmsensor to 0.3 (#2883) --- homeassistant/components/sensor/serial_pm.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/serial_pm.py b/homeassistant/components/sensor/serial_pm.py index a86fea74cea..b5e200eaa24 100644 --- a/homeassistant/components/sensor/serial_pm.py +++ b/homeassistant/components/sensor/serial_pm.py @@ -12,7 +12,7 @@ from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA -REQUIREMENTS = ['pmsensor==0.2'] +REQUIREMENTS = ['pmsensor==0.3'] _LOGGER = logging.getLogger(__name__) @@ -29,7 +29,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the available PM sensors.""" - from pmsensor import serial_data_collector as pm + from pmsensor import serial_pm as pm try: coll = pm.PMDataCollector(config.get(CONF_SERIAL_DEVICE), diff --git a/requirements_all.txt b/requirements_all.txt index 94d610cdee1..ed18e1a9d2a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -255,7 +255,7 @@ pilight==0.0.2 plexapi==2.0.2 # homeassistant.components.sensor.serial_pm -pmsensor==0.2 +pmsensor==0.3 # homeassistant.components.climate.proliphix # homeassistant.components.thermostat.proliphix From 4f1712c93317cb8acab1728000d2bec37c0c283f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 19 Aug 2016 14:57:14 +0200 Subject: [PATCH 096/193] Use voluptuous for system monitoring sensors (#2813) * Use voluptuous for system monitoring sensors * Extent platform, ordering, and consts * Add resource/resources --- homeassistant/components/sensor/cpuspeed.py | 21 ++++++--- homeassistant/components/sensor/glances.py | 43 ++++++++++--------- .../components/sensor/systemmonitor.py | 23 +++++++--- homeassistant/const.py | 2 + 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/sensor/cpuspeed.py b/homeassistant/components/sensor/cpuspeed.py index f3bd2dac9e2..393c1cd7257 100644 --- a/homeassistant/components/sensor/cpuspeed.py +++ b/homeassistant/components/sensor/cpuspeed.py @@ -6,27 +6,38 @@ https://home-assistant.io/components/sensor.cpuspeed/ """ import logging +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity REQUIREMENTS = ['py-cpuinfo==0.2.3'] -_LOGGER = logging.getLogger(__name__) - -DEFAULT_NAME = "CPU speed" +DEFAULT_NAME = 'CPU speed' ATTR_VENDOR = 'Vendor ID' ATTR_BRAND = 'Brand' ATTR_HZ = 'GHz Advertised' ICON = 'mdi:pulse' +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) + # pylint: disable=unused-variable def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the CPU speed sensor.""" - add_devices([CpuSpeedSensor(config.get('name', DEFAULT_NAME))]) + name = config.get(CONF_NAME) + + add_devices([CpuSpeedSensor(name)]) class CpuSpeedSensor(Entity): - """Representation a CPU sensor.""" + """Representation of a CPU sensor.""" def __init__(self, name): """Initialize the sensor.""" diff --git a/homeassistant/components/sensor/glances.py b/homeassistant/components/sensor/glances.py index 4ebe8d797a5..12f8d46090a 100644 --- a/homeassistant/components/sensor/glances.py +++ b/homeassistant/components/sensor/glances.py @@ -8,17 +8,20 @@ import logging from datetime import timedelta import requests +import voluptuous as vol -from homeassistant.const import STATE_UNKNOWN +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_HOST, CONF_PORT, STATE_UNKNOWN, CONF_NAME, CONF_RESOURCES) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv -_LOGGER = logging.getLogger(__name__) +DEFAULT_NAME = 'Glances' +DEFAULT_HOST = 'localhost' +_RESOURCE = 'api/2/all' +DEFAULT_PORT = '61208' -_RESOURCE = '/api/2/all' -CONF_HOST = 'host' -CONF_PORT = '61208' -CONF_RESOURCES = 'resources' SENSOR_TYPES = { 'disk_use_percent': ['Disk Use', '%'], 'disk_use': ['Disk Use', 'GiB'], @@ -36,7 +39,16 @@ SENSOR_TYPES = { 'process_sleeping': ['Sleeping', None] } +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_RESOURCES, default=['disk_use']): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), +}) + _LOGGER = logging.getLogger(__name__) + # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) @@ -44,25 +56,17 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) # pylint: disable=unused-variable def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Glances sensor.""" + name = config.get(CONF_NAME) host = config.get(CONF_HOST) - port = config.get('port', CONF_PORT) - url = 'http://{}:{}{}'.format(host, port, _RESOURCE) + port = config.get(CONF_PORT) + url = 'http://{}:{}/{}'.format(host, port, _RESOURCE) var_conf = config.get(CONF_RESOURCES) - if None in (host, var_conf): - _LOGGER.error('Not all required config keys present: %s', - ', '.join((CONF_HOST, CONF_RESOURCES))) - return False - try: response = requests.get(url, timeout=10) if not response.ok: _LOGGER.error('Response status is "%s"', response.status_code) return False - except requests.exceptions.MissingSchema: - _LOGGER.error("Missing resource or schema in configuration. " - "Please check the details in the configuration file") - return False except requests.exceptions.ConnectionError: _LOGGER.error("No route to resource/endpoint: %s", url) return False @@ -71,10 +75,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): dev = [] for resource in var_conf: - if resource not in SENSOR_TYPES: - _LOGGER.error('Sensor type: "%s" does not exist', resource) - else: - dev.append(GlancesSensor(rest, config.get('name'), resource)) + dev.append(GlancesSensor(rest, name, resource)) add_devices(dev) diff --git a/homeassistant/components/sensor/systemmonitor.py b/homeassistant/components/sensor/systemmonitor.py index c9767428aaa..0455ffb6428 100755 --- a/homeassistant/components/sensor/systemmonitor.py +++ b/homeassistant/components/sensor/systemmonitor.py @@ -6,11 +6,17 @@ https://home-assistant.io/components/sensor.systemmonitor/ """ import logging +import voluptuous as vol + import homeassistant.util.dt as dt_util -from homeassistant.const import STATE_OFF, STATE_ON + +from homeassistant.const import (CONF_RESOURCES, STATE_OFF, STATE_ON) +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['psutil==4.3.0'] + SENSOR_TYPES = { 'disk_use_percent': ['Disk Use', '%', 'mdi:harddisk'], 'disk_use': ['Disk Use', 'GiB', 'mdi:harddisk'], @@ -33,6 +39,14 @@ SENSOR_TYPES = { 'since_last_boot': ['Since Last Boot', '', 'mdi:clock'] } +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_RESOURCES, default=['disk_use']): + vol.All(cv.ensure_list, [vol.Schema({ + vol.Required('type'): vol.In(SENSOR_TYPES), + vol.Optional('arg'): cv.string, + })]) +}) + _LOGGER = logging.getLogger(__name__) @@ -40,13 +54,10 @@ _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the System sensors.""" dev = [] - for resource in config['resources']: + for resource in config[CONF_RESOURCES]: if 'arg' not in resource: resource['arg'] = '' - if resource['type'] not in SENSOR_TYPES: - _LOGGER.error('Sensor type: "%s" does not exist', resource['type']) - else: - dev.append(SystemMonitorSensor(resource['type'], resource['arg'])) + dev.append(SystemMonitorSensor(resource['type'], resource['arg'])) add_devices(dev) diff --git a/homeassistant/const.py b/homeassistant/const.py index 10ddcc2f7cc..d8c1f3d5a0d 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -50,6 +50,8 @@ CONF_PAYLOAD = 'payload' CONF_PENDING_TIME = 'pending_time' CONF_PLATFORM = 'platform' CONF_PORT = 'port' +CONF_RESOURCE = 'resource' +CONF_RESOURCES = 'resources' CONF_SCAN_INTERVAL = 'scan_interval' CONF_STATE = 'state' CONF_TEMPERATURE_UNIT = 'temperature_unit' From 337b2e3f7746c28bc7b96464618d149474e29cd1 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 19 Aug 2016 20:07:09 +0100 Subject: [PATCH 097/193] Add voluptuous .# Please enter the commit message for your changes. Lines starting --- homeassistant/components/sensor/loopenergy.py | 83 +++++++++++-------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/sensor/loopenergy.py b/homeassistant/components/sensor/loopenergy.py index 3394e69da8d..d186642e889 100644 --- a/homeassistant/components/sensor/loopenergy.py +++ b/homeassistant/components/sensor/loopenergy.py @@ -6,56 +6,67 @@ https://home-assistant.io/components/sensor.loop_energy/ """ import logging +import voluptuous as vol +import homeassistant.helpers.config_validation as cv + from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import EVENT_HOMEASSISTANT_STOP -from homeassistant.util import convert _LOGGER = logging.getLogger(__name__) -DOMAIN = "loopenergy" - REQUIREMENTS = ['pyloopenergy==0.0.14'] +CONFIG_ELEC = 'electricity' +CONFIG_GAS = 'gas' + +CONFIG_ELEC_SERIAL = 'electricity_serial' +CONFIG_ELEC_SECRET = 'electricity_secret' + +CONFIG_GAS_SERIAL = 'gas_serial' +CONFIG_GAS_SECRET = 'gas_secret' +CONFIG_GAS_CALORIFIC = 'gas_calorific' + +CONFIG_GAS_TYPE = 'gas_type' + +ELEC_SCHEMA = vol.Schema({ + vol.Required(CONFIG_ELEC_SERIAL): cv.string, + vol.Required(CONFIG_ELEC_SECRET): cv.string, +}) + +GAS_TYPE_SCHEMA = vol.In(['imperial', 'metric']) + +GAS_SCHEMA = vol.Schema({ + vol.Required(CONFIG_GAS_SERIAL): cv.string, + vol.Required(CONFIG_GAS_SECRET): cv.string, + vol.Optional(CONFIG_GAS_TYPE, default='metric'): + GAS_TYPE_SCHEMA, + vol.Optional(CONFIG_GAS_CALORIFIC, default=39.11): vol.Coerce(float) +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONFIG_ELEC): vol.All( + dict, ELEC_SCHEMA), + vol.Optional(CONFIG_GAS, default={}): vol.All( + dict, GAS_SCHEMA) +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Loop Energy sensors.""" import pyloopenergy - elec_serial = config.get('electricity_serial') - elec_secret = config.get('electricity_secret') - gas_serial = config.get('gas_serial') - gas_secret = config.get('gas_secret') - gas_type = config.get('gas_type', 'metric') - gas_calorific = convert(config.get('gas_calorific'), float, 39.11) - - if not (elec_serial and elec_secret): - _LOGGER.error( - "Configuration Error, " - "please make sure you have configured electricity " - "serial and secret tokens") - return None - - if (gas_serial or gas_secret) and not (gas_serial and gas_secret): - _LOGGER.error( - "Configuration Error, " - "please make sure you have configured gas " - "serial and secret tokens") - return None - - if gas_type not in ['imperial', 'metric']: - _LOGGER.error( - "Configuration Error, 'gas_type' " - "can only be 'imperial' or 'metric' ") - return None + elec_config = config.get(CONFIG_ELEC) + gas_config = config.get(CONFIG_GAS) # pylint: disable=too-many-function-args controller = pyloopenergy.LoopEnergy( - elec_serial, - elec_secret, - gas_serial, - gas_secret, - gas_type, - gas_calorific + elec_config.get(CONFIG_ELEC_SERIAL), + elec_config.get(CONFIG_ELEC_SECRET), + gas_config.get(CONFIG_GAS_SERIAL), + gas_config.get(CONFIG_GAS_SECRET), + gas_config.get(CONFIG_GAS_TYPE), + gas_config.get(CONFIG_GAS_CALORIFIC) ) def stop_loopenergy(event): @@ -67,7 +78,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors = [LoopEnergyElec(controller)] - if gas_serial: + if gas_config.get(CONFIG_GAS_SERIAL): sensors.append(LoopEnergyGas(controller)) add_devices(sensors) From d1a31b3e0c51cb885c84c8779a1f55d5f732ddeb Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 19 Aug 2016 21:47:07 +0100 Subject: [PATCH 098/193] Change CONFIG to CONF for consistency. --- homeassistant/components/sensor/loopenergy.py | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/sensor/loopenergy.py b/homeassistant/components/sensor/loopenergy.py index d186642e889..04a1d946d45 100644 --- a/homeassistant/components/sensor/loopenergy.py +++ b/homeassistant/components/sensor/loopenergy.py @@ -17,37 +17,37 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['pyloopenergy==0.0.14'] -CONFIG_ELEC = 'electricity' -CONFIG_GAS = 'gas' +CONF_ELEC = 'electricity' +CONF_GAS = 'gas' -CONFIG_ELEC_SERIAL = 'electricity_serial' -CONFIG_ELEC_SECRET = 'electricity_secret' +CONF_ELEC_SERIAL = 'electricity_serial' +CONF_ELEC_SECRET = 'electricity_secret' -CONFIG_GAS_SERIAL = 'gas_serial' -CONFIG_GAS_SECRET = 'gas_secret' -CONFIG_GAS_CALORIFIC = 'gas_calorific' +CONF_GAS_SERIAL = 'gas_serial' +CONF_GAS_SECRET = 'gas_secret' +CONF_GAS_CALORIFIC = 'gas_calorific' -CONFIG_GAS_TYPE = 'gas_type' +CONF_GAS_TYPE = 'gas_type' ELEC_SCHEMA = vol.Schema({ - vol.Required(CONFIG_ELEC_SERIAL): cv.string, - vol.Required(CONFIG_ELEC_SECRET): cv.string, + vol.Required(CONF_ELEC_SERIAL): cv.string, + vol.Required(CONF_ELEC_SECRET): cv.string, }) GAS_TYPE_SCHEMA = vol.In(['imperial', 'metric']) GAS_SCHEMA = vol.Schema({ - vol.Required(CONFIG_GAS_SERIAL): cv.string, - vol.Required(CONFIG_GAS_SECRET): cv.string, - vol.Optional(CONFIG_GAS_TYPE, default='metric'): + vol.Required(CONF_GAS_SERIAL): cv.string, + vol.Required(CONF_GAS_SECRET): cv.string, + vol.Optional(CONF_GAS_TYPE, default='metric'): GAS_TYPE_SCHEMA, - vol.Optional(CONFIG_GAS_CALORIFIC, default=39.11): vol.Coerce(float) + vol.Optional(CONF_GAS_CALORIFIC, default=39.11): vol.Coerce(float) }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONFIG_ELEC): vol.All( + vol.Required(CONF_ELEC): vol.All( dict, ELEC_SCHEMA), - vol.Optional(CONFIG_GAS, default={}): vol.All( + vol.Optional(CONF_GAS, default={}): vol.All( dict, GAS_SCHEMA) }) @@ -56,17 +56,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Loop Energy sensors.""" import pyloopenergy - elec_config = config.get(CONFIG_ELEC) - gas_config = config.get(CONFIG_GAS) + elec_config = config.get(CONF_ELEC) + gas_config = config.get(CONF_GAS) # pylint: disable=too-many-function-args controller = pyloopenergy.LoopEnergy( - elec_config.get(CONFIG_ELEC_SERIAL), - elec_config.get(CONFIG_ELEC_SECRET), - gas_config.get(CONFIG_GAS_SERIAL), - gas_config.get(CONFIG_GAS_SECRET), - gas_config.get(CONFIG_GAS_TYPE), - gas_config.get(CONFIG_GAS_CALORIFIC) + elec_config.get(CONF_ELEC_SERIAL), + elec_config.get(CONF_ELEC_SECRET), + gas_config.get(CONF_GAS_SERIAL), + gas_config.get(CONF_GAS_SECRET), + gas_config.get(CONF_GAS_TYPE), + gas_config.get(CONF_GAS_CALORIFIC) ) def stop_loopenergy(event): @@ -78,7 +78,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors = [LoopEnergyElec(controller)] - if gas_config.get(CONFIG_GAS_SERIAL): + if gas_config.get(CONF_GAS_SERIAL): sensors.append(LoopEnergyGas(controller)) add_devices(sensors) From 712f1498ae2b605a781896c934778720f451cde2 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 19 Aug 2016 22:43:40 +0100 Subject: [PATCH 099/193] Add voluptuous to Vera. --- homeassistant/components/vera.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/vera.py b/homeassistant/components/vera.py index 514fe002568..3e4ada562ce 100644 --- a/homeassistant/components/vera.py +++ b/homeassistant/components/vera.py @@ -7,12 +7,14 @@ https://home-assistant.io/components/vera/ import logging from collections import defaultdict -from requests.exceptions import RequestException +import voluptuous as vol +from requests.exceptions import RequestException from homeassistant.util.dt import utc_from_timestamp from homeassistant.util import convert from homeassistant.helpers import discovery +from homeassistant.helpers import config_validation as cv from homeassistant.const import ( ATTR_ARMED, ATTR_BATTERY_LEVEL, ATTR_LAST_TRIP_TIME, ATTR_TRIPPED, EVENT_HOMEASSISTANT_STOP) @@ -26,6 +28,7 @@ DOMAIN = 'vera' VERA_CONTROLLER = None +CONF_CONTROLLER = 'vera_controller_url' CONF_EXCLUDE = 'exclude' CONF_LIGHTS = 'lights' @@ -33,6 +36,16 @@ ATTR_CURRENT_POWER_MWH = "current_power_mwh" VERA_DEVICES = defaultdict(list) +VERA_ID_LIST_SCHEMA = vol.Schema([int]) + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_CONTROLLER): cv.url, + vol.Optional(CONF_EXCLUDE, default=[]): VERA_ID_LIST_SCHEMA, + vol.Optional(CONF_LIGHTS, default=[]): VERA_ID_LIST_SCHEMA, + }), +}, extra=vol.ALLOW_EXTRA) + # pylint: disable=unused-argument, too-many-function-args def setup(hass, base_config): @@ -42,13 +55,6 @@ def setup(hass, base_config): config = base_config.get(DOMAIN) base_url = config.get('vera_controller_url') - if not base_url: - _LOGGER.error( - "The required parameter 'vera_controller_url'" - " was not found in config" - ) - return False - VERA_CONTROLLER, _ = veraApi.init_controller(base_url) def stop_subscription(event): @@ -65,15 +71,9 @@ def setup(hass, base_config): _LOGGER.exception("Error communicating with Vera API") return False - exclude = config.get(CONF_EXCLUDE, []) - if not isinstance(exclude, list): - _LOGGER.error("'exclude' must be a list of device_ids") - return False + exclude = config.get(CONF_EXCLUDE) - lights_ids = config.get(CONF_LIGHTS, []) - if not isinstance(lights_ids, list): - _LOGGER.error("'lights' must be a list of device_ids") - return False + lights_ids = config.get(CONF_LIGHTS) for device in all_devices: if device.device_id in exclude: From a50463d2f1666a01aff3346977f9c54099ad785d Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 20 Aug 2016 00:20:41 +0200 Subject: [PATCH 100/193] Improve homematic climate support (#2894) --- homeassistant/components/climate/homematic.py | 59 ++++++++++++++++++- homeassistant/components/homematic.py | 3 +- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/climate/homematic.py b/homeassistant/components/climate/homematic.py index da160bab56e..be81bb9326e 100644 --- a/homeassistant/components/climate/homematic.py +++ b/homeassistant/components/climate/homematic.py @@ -6,12 +6,21 @@ https://home-assistant.io/components/climate.homematic/ """ import logging import homeassistant.components.homematic as homematic -from homeassistant.components.climate import ClimateDevice +from homeassistant.components.climate import ClimateDevice, STATE_AUTO from homeassistant.util.temperature import convert from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN DEPENDENCIES = ['homematic'] +STATE_MANUAL = "manual" +STATE_BOOST = "boost" + +HM_STATE_MAP = { + "AUTO_MODE": STATE_AUTO, + "MANU_MODE": STATE_MANUAL, + "BOOST_MODE": STATE_BOOST, +} + _LOGGER = logging.getLogger(__name__) @@ -34,19 +43,52 @@ class HMThermostat(homematic.HMDevice, ClimateDevice): """Return the unit of measurement that is used.""" return TEMP_CELSIUS + @property + def current_operation(self): + """Return current operation ie. heat, cool, idle.""" + if not self.available: + return None + + # read state and search + for mode, state in HM_STATE_MAP.items(): + code = getattr(self._hmdevice, mode, 0) + if self._data.get('CONTROL_MODE') == code: + return state + + @property + def operation_list(self): + """List of available operation modes.""" + if not self.available: + return None + op_list = [] + + # generate list + for mode in self._hmdevice.ACTIONNODE: + if mode in HM_STATE_MAP: + op_list.append(HM_STATE_MAP.get(mode)) + + return op_list + + @property + def current_humidity(self): + """Return the current humidity.""" + if not self.available: + return None + return self._data.get('ACTUAL_HUMIDITY', None) + @property def current_temperature(self): """Return the current temperature.""" if not self.available: return None - return self._data["ACTUAL_TEMPERATURE"] + return self._data.get('ACTUAL_TEMPERATURE', None) @property def target_temperature(self): """Return the target temperature.""" if not self.available: return None - return self._data["SET_TEMPERATURE"] + return self._data.get('SET_TEMPERATURE', None) def set_temperature(self, temperature): """Set new target temperature.""" @@ -54,6 +96,13 @@ class HMThermostat(homematic.HMDevice, ClimateDevice): return None self._hmdevice.set_temperature(temperature) + def set_operation_mode(self, operation_mode): + """Set new target operation mode.""" + for mode, state in HM_STATE_MAP.items(): + if state == operation_mode: + code = getattr(self._hmdevice, mode, 0) + self._hmdevice.STATE = code + @property def min_temp(self): """Return the minimum temperature - 4.5 means off.""" @@ -88,3 +137,7 @@ class HMThermostat(homematic.HMDevice, ClimateDevice): self._data.update({"CONTROL_MODE": STATE_UNKNOWN, "SET_TEMPERATURE": STATE_UNKNOWN, "ACTUAL_TEMPERATURE": STATE_UNKNOWN}) + + # support humidity + if 'ACTUAL_HUMIDITY' in self._hmdevice.SENSORNODE: + self._data.update({'ACTUAL_HUMIDITY': STATE_UNKNOWN}) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index fe65929a346..942e4b1c741 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -55,7 +55,8 @@ HM_DEVICE_TYPES = { } HM_IGNORE_DISCOVERY_NODE = [ - 'ACTUAL_TEMPERATURE' + 'ACTUAL_TEMPERATURE', + 'ACTUAL_HUMIDITY' ] HM_ATTRIBUTE_SUPPORT = { From 6e672b7beef016f22b4c981b4a8a2a0f511c1fba Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Sat, 20 Aug 2016 13:59:23 +0200 Subject: [PATCH 101/193] More generic use of up and down commands plus a workaround for SOMFY controller. (#2852) * Support older devices * Update with workaround * Inverted up and down * Make dual arguments --- .../components/rollershutter/zwave.py | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/rollershutter/zwave.py b/homeassistant/components/rollershutter/zwave.py index efe93b3db79..1e193830005 100644 --- a/homeassistant/components/rollershutter/zwave.py +++ b/homeassistant/components/rollershutter/zwave.py @@ -15,6 +15,15 @@ from homeassistant.components.rollershutter import RollershutterDevice COMMAND_CLASS_SWITCH_MULTILEVEL = 0x26 # 38 COMMAND_CLASS_SWITCH_BINARY = 0x25 # 37 +SOMFY = 0x47 +SOMFY_ZRTSI = 0x5a52 +SOMFY_ZRTSI_CONTROLLER = (SOMFY, SOMFY_ZRTSI) +WORKAROUND = 'workaround' + +DEVICE_MAPPINGS = { + SOMFY_ZRTSI_CONTROLLER: WORKAROUND +} + _LOGGER = logging.getLogger(__name__) @@ -48,8 +57,18 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice): self._lozwmgr.create() self._node = value.node self._current_position = None + self._workaround = None dispatcher.connect( self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) + if (value.node.manufacturer_id.strip() and + value.node.product_id.strip()): + specific_sensor_key = (int(value.node.manufacturer_id, 16), + int(value.node.product_type, 16)) + + if specific_sensor_key in DEVICE_MAPPINGS: + if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND: + _LOGGER.debug("Controller without positioning feedback") + self._workaround = 1 def value_changed(self, value): """Called when a value has changed on the network.""" @@ -71,20 +90,23 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice): @property def current_position(self): """Return the current position of Zwave roller shutter.""" - if self._current_position is not None: - if self._current_position <= 5: - return 100 - elif self._current_position >= 95: - return 0 - else: - return 100 - self._current_position + if not self._workaround: + if self._current_position is not None: + if self._current_position <= 5: + return 100 + elif self._current_position >= 95: + return 0 + else: + return 100 - self._current_position def move_up(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': + and value.label == 'Open' or \ + value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ + and value.label == 'Down': self._lozwmgr.pressButton(value.value_id) break @@ -93,6 +115,8 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice): 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': self._lozwmgr.pressButton(value.value_id) break @@ -106,6 +130,8 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, RollershutterDevice): 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': + and value.label == 'Open' or \ + value.command_class == zwave.COMMAND_CLASS_SWITCH_MULTILEVEL \ + and value.label == 'Down': self._lozwmgr.releaseButton(value.value_id) break From 482f32bb8796f90acd61d4895849ed4391076053 Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Sat, 20 Aug 2016 13:03:57 +0100 Subject: [PATCH 102/193] Add voluptuous to wemo. (#2895) --- homeassistant/components/wemo.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/wemo.py b/homeassistant/components/wemo.py index 00a7017fa0f..5fe124aaf45 100644 --- a/homeassistant/components/wemo.py +++ b/homeassistant/components/wemo.py @@ -6,8 +6,12 @@ https://home-assistant.io/components/wemo/ """ import logging +import voluptuous as vol + from homeassistant.components.discovery import SERVICE_WEMO from homeassistant.helpers import discovery +from homeassistant.helpers import config_validation as cv + from homeassistant.const import EVENT_HOMEASSISTANT_STOP REQUIREMENTS = ['pywemo==0.4.5'] @@ -29,6 +33,14 @@ KNOWN_DEVICES = [] _LOGGER = logging.getLogger(__name__) +CONF_STATIC = 'static' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_STATIC, default=[]): vol.Schema([cv.string]) + }), +}, extra=vol.ALLOW_EXTRA) + # pylint: disable=unused-argument, too-many-function-args def setup(hass, config): @@ -69,7 +81,7 @@ def setup(hass, config): # Add static devices from the config file. devices.extend((address, None) - for address in config.get(DOMAIN, {}).get('static', [])) + for address in config.get(DOMAIN, {}).get(CONF_STATIC)) for address, device in devices: port = pywemo.ouimeaux_device.probe_wemo(address) From 8eb66ac2b8649d5a7403bf1afda53c91cc7d1581 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sat, 20 Aug 2016 08:36:28 -0400 Subject: [PATCH 103/193] Ensure Slack messages appear as correct user (#2893) Current documentation suggests to use personal API tokens. This isn't ideal because for a few reasons: * messages will come as your own user, so it's hard to tell it's coming from hass * it's harder to manage if multiple people are using Slack and home * assistant, since you'd have to coordinate rolling of it It is possible to use Slack bot users already. Just make a new one from https://your-team.slack.com/apps/build/custom-integration, and use the token for that. You can even add an icon from the web frontend for home assistant. However, the message will appear as a bot without a name or icon. This pull requests fixes this by passing the as_user parameter, which uses the bot user's name and icon. One caveat is you need to invite the bot user into the room you want to post to. This probably was an issue before though. :tophat: to @jnewland who pointed me to this in his branch --- homeassistant/components/notify/slack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/notify/slack.py b/homeassistant/components/notify/slack.py index 141cf6887e9..99d0c4ef663 100644 --- a/homeassistant/components/notify/slack.py +++ b/homeassistant/components/notify/slack.py @@ -52,6 +52,6 @@ class SlackNotificationService(BaseNotificationService): channel = kwargs.get('target') or self._default_channel try: - self.slack.chat.post_message(channel, message) + self.slack.chat.post_message(channel, message, as_user=True) except slacker.Error: _LOGGER.exception("Could not send slack notification") From c0cd2d749f5ebcfc12591b544c0f2943e1d273c3 Mon Sep 17 00:00:00 2001 From: pavoni Date: Sat, 20 Aug 2016 15:43:07 +0100 Subject: [PATCH 104/193] Tidy. --- homeassistant/components/vera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/vera.py b/homeassistant/components/vera.py index 3e4ada562ce..f6162f5582c 100644 --- a/homeassistant/components/vera.py +++ b/homeassistant/components/vera.py @@ -54,7 +54,7 @@ def setup(hass, base_config): import pyvera as veraApi config = base_config.get(DOMAIN) - base_url = config.get('vera_controller_url') + base_url = config.get(CONF_CONTROLLER) VERA_CONTROLLER, _ = veraApi.init_controller(base_url) def stop_subscription(event): From b5cc145a92004cbc722bd1607a5343aa7cf73d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Sandstr=C3=B6m?= Date: Sat, 20 Aug 2016 17:08:42 +0200 Subject: [PATCH 105/193] bump vsure version --- homeassistant/components/verisure.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/verisure.py b/homeassistant/components/verisure.py index 601264c70f8..901b577a9a0 100644 --- a/homeassistant/components/verisure.py +++ b/homeassistant/components/verisure.py @@ -15,7 +15,7 @@ from homeassistant.util import Throttle DOMAIN = "verisure" -REQUIREMENTS = ['vsure==0.8.1'] +REQUIREMENTS = ['vsure==0.10.1'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index ed18e1a9d2a..bea3f9a0282 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -469,7 +469,7 @@ urllib3 uvcclient==0.9.0 # homeassistant.components.verisure -vsure==0.8.1 +vsure==0.10.1 # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 From 8d1a9d86ea302254dd956b48fe3b529d38f0d834 Mon Sep 17 00:00:00 2001 From: Teagan Glenn Date: Sat, 20 Aug 2016 13:39:56 -0600 Subject: [PATCH 106/193] Yaml secret fallback to parent folders (#2878) * Move secret cache out of loader so it can be referenced by other folders * Unit test to verify secrets from another folder work & see if it overrides parent secret * Clear secret cache after load --- homeassistant/bootstrap.py | 3 ++ homeassistant/util/yaml.py | 67 ++++++++++++++++++++++---------------- tests/util/test_yaml.py | 53 ++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 30 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index c7fb9096a56..b61bce1a58f 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -19,6 +19,7 @@ import homeassistant.config as conf_util import homeassistant.core as core import homeassistant.loader as loader import homeassistant.util.package as pkg_util +from homeassistant.util.yaml import clear_secret_cache from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import ( @@ -308,6 +309,8 @@ def from_config_file(config_path: str, config_dict = conf_util.load_yaml_config_file(config_path) except HomeAssistantError: return None + finally: + clear_secret_cache() return from_config_dict(config_dict, hass, enable_log=False, skip_pip=skip_pip) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index c88daaab69a..ddbd70c4248 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -2,6 +2,7 @@ import glob import logging import os +import sys from collections import OrderedDict from typing import Union, List, Dict @@ -16,6 +17,7 @@ from homeassistant.exceptions import HomeAssistantError _LOGGER = logging.getLogger(__name__) _SECRET_NAMESPACE = 'homeassistant' _SECRET_YAML = 'secrets.yaml' +__SECRET_CACHE = {} # type: Dict # pylint: disable=too-many-ancestors @@ -43,6 +45,11 @@ def load_yaml(fname: str) -> Union[List, Dict]: raise HomeAssistantError(exc) +def clear_secret_cache() -> None: + """Clear the secrete cache.""" + __SECRET_CACHE.clear() + + def _include_yaml(loader: SafeLineLoader, node: yaml.nodes.Node) -> Union[List, Dict]: """Load another YAML file and embeds it using the !include tag. @@ -140,40 +147,44 @@ def _env_var_yaml(loader: SafeLineLoader, raise HomeAssistantError(node.value) +def _load_secret_yaml(secret_path: str) -> Dict: + """Load the secrets yaml from path.""" + _LOGGER.debug('Loading %s', os.path.join(secret_path, _SECRET_YAML)) + secrets = {} + if os.path.isfile(os.path.join(secret_path, _SECRET_YAML)): + secrets = load_yaml( + os.path.join(secret_path, _SECRET_YAML)) + if 'logger' in secrets: + logger = str(secrets['logger']).lower() + if logger == 'debug': + _LOGGER.setLevel(logging.DEBUG) + else: + _LOGGER.error("secrets.yaml: 'logger: debug' expected," + " but 'logger: %s' found", logger) + del secrets['logger'] + return secrets + + # pylint: disable=protected-access def _secret_yaml(loader: SafeLineLoader, node: yaml.nodes.Node): """Load secrets and embed it into the configuration YAML.""" - # Create secret cache on loader and load secrets.yaml - if not hasattr(loader, '_SECRET_CACHE'): - loader._SECRET_CACHE = {} + secret_path = os.path.dirname(loader.name) + while os.path.exists(secret_path) and not secret_path == os.path.dirname( + sys.path[0]): + secrets = __SECRET_CACHE.get(secret_path, + _load_secret_yaml(secret_path)) + if node.value in secrets: + _LOGGER.debug('Secret %s retrieved from secrets.yaml in ' + 'folder %s', node.value, secret_path) + return secrets[node.value] + next_path = os.path.dirname(secret_path) - secret_path = os.path.join(os.path.dirname(loader.name), _SECRET_YAML) - if secret_path not in loader._SECRET_CACHE: - if os.path.isfile(secret_path): - loader._SECRET_CACHE[secret_path] = load_yaml(secret_path) - secrets = loader._SECRET_CACHE[secret_path] - if 'logger' in secrets: - logger = str(secrets['logger']).lower() - if logger == 'debug': - _LOGGER.setLevel(logging.DEBUG) - else: - _LOGGER.error("secrets.yaml: 'logger: debug' expected," - " but 'logger: %s' found", logger) - del secrets['logger'] - else: - loader._SECRET_CACHE[secret_path] = None - secrets = loader._SECRET_CACHE[secret_path] + if not next_path or next_path == secret_path: + # Somehow we got past the .homeassistant configuration folder... + break - # Retrieve secret, first from secrets.yaml, then from keyring - if secrets is not None and node.value in secrets: - _LOGGER.debug('Secret %s retrieved from secrets.yaml.', node.value) - return secrets[node.value] - for sname, sdict in loader._SECRET_CACHE.items(): - if node.value in sdict: - _LOGGER.debug('Secret %s retrieved from secrets.yaml in other ' - 'folder %s', node.value, sname) - return sdict[node.value] + secret_path = next_path if keyring: # do ome keyring stuff diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py index 7bede7edca9..4ce0def08ac 100644 --- a/tests/util/test_yaml.py +++ b/tests/util/test_yaml.py @@ -3,6 +3,7 @@ import io import unittest import os import tempfile +from homeassistant.exceptions import HomeAssistantError from homeassistant.util import yaml import homeassistant.config as config_util from tests.common import get_test_config_dir @@ -165,9 +166,16 @@ class TestSecrets(unittest.TestCase): def setUp(self): # pylint: disable=invalid-name """Create & load secrets file.""" config_dir = get_test_config_dir() + yaml.clear_secret_cache() self._yaml_path = os.path.join(config_dir, config_util.YAML_CONFIG_FILE) - self._secret_path = os.path.join(config_dir, 'secrets.yaml') + self._secret_path = os.path.join(config_dir, yaml._SECRET_YAML) + self._sub_folder_path = os.path.join(config_dir, 'subFolder') + if not os.path.exists(self._sub_folder_path): + os.makedirs(self._sub_folder_path) + self._unrelated_path = os.path.join(config_dir, 'unrelated') + if not os.path.exists(self._unrelated_path): + os.makedirs(self._unrelated_path) load_yaml(self._secret_path, 'http_pw: pwhttp\n' @@ -185,7 +193,11 @@ class TestSecrets(unittest.TestCase): def tearDown(self): # pylint: disable=invalid-name """Clean up secrets.""" - for path in [self._yaml_path, self._secret_path]: + yaml.clear_secret_cache() + for path in [self._yaml_path, self._secret_path, + os.path.join(self._sub_folder_path, 'sub.yaml'), + os.path.join(self._sub_folder_path, yaml._SECRET_YAML), + os.path.join(self._unrelated_path, yaml._SECRET_YAML)]: if os.path.isfile(path): os.remove(path) @@ -199,6 +211,43 @@ class TestSecrets(unittest.TestCase): 'password': 'pw1'} self.assertEqual(expected, self._yaml['component']) + def test_secrets_from_parent_folder(self): + """Test loading secrets from parent foler.""" + expected = {'api_password': 'pwhttp'} + self._yaml = load_yaml(os.path.join(self._sub_folder_path, 'sub.yaml'), + 'http:\n' + ' api_password: !secret http_pw\n' + 'component:\n' + ' username: !secret comp1_un\n' + ' password: !secret comp1_pw\n' + '') + + self.assertEqual(expected, self._yaml['http']) + + def test_secret_overrides_parent(self): + """Test loading current directory secret overrides the parent.""" + expected = {'api_password': 'override'} + load_yaml(os.path.join(self._sub_folder_path, yaml._SECRET_YAML), + 'http_pw: override') + self._yaml = load_yaml(os.path.join(self._sub_folder_path, 'sub.yaml'), + 'http:\n' + ' api_password: !secret http_pw\n' + 'component:\n' + ' username: !secret comp1_un\n' + ' password: !secret comp1_pw\n' + '') + + self.assertEqual(expected, self._yaml['http']) + + def test_secrets_from_unrelated_fails(self): + """Test loading secrets from unrelated folder fails.""" + load_yaml(os.path.join(self._unrelated_path, yaml._SECRET_YAML), + 'test: failure') + with self.assertRaises(HomeAssistantError): + load_yaml(os.path.join(self._sub_folder_path, 'sub.yaml'), + 'http:\n' + ' api_password: !secret test') + def test_secrets_keyring(self): """Test keyring fallback & get_password.""" yaml.keyring = None # Ensure its not there From 7d0c50a106bc6f04b73060e42a7f51d8a41ab516 Mon Sep 17 00:00:00 2001 From: Henning Dickten Date: Sat, 20 Aug 2016 18:41:31 +0200 Subject: [PATCH 107/193] Update pymysensors version to 0.7 --- homeassistant/components/mysensors.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index b950ec39dd8..82deb67064b 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -29,7 +29,7 @@ DOMAIN = 'mysensors' DEPENDENCIES = [] REQUIREMENTS = [ 'https://github.com/theolind/pymysensors/archive/' - 'cc5d0b325e13c2b623fa934f69eea7cd4555f110.zip#pymysensors==0.6'] + 'd59e2548f8378371f7fcb0805f7800796a6fa044.zip#pymysensors==0.7'] _LOGGER = logging.getLogger(__name__) ATTR_NODE_ID = 'node_id' ATTR_CHILD_ID = 'child_id' diff --git a/requirements_all.txt b/requirements_all.txt index bea3f9a0282..52825484870 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -185,7 +185,7 @@ https://github.com/robbiet480/pygtfs/archive/00546724e4bbcb3053110d844ca44e22462 https://github.com/sander76/powerviewApi/archive/master.zip#powerviewApi==0.2 # homeassistant.components.mysensors -https://github.com/theolind/pymysensors/archive/cc5d0b325e13c2b623fa934f69eea7cd4555f110.zip#pymysensors==0.6 +https://github.com/theolind/pymysensors/archive/d59e2548f8378371f7fcb0805f7800796a6fa044.zip#pymysensors==0.7 # homeassistant.components.alarm_control_panel.simplisafe https://github.com/w1ll1am23/simplisafe-python/archive/586fede0e85fd69e56e516aaa8e97eb644ca8866.zip#simplisafe-python==0.0.1 From 25585012358c828f6fd692896369d9d375eeec01 Mon Sep 17 00:00:00 2001 From: Daniel Perna Date: Sun, 21 Aug 2016 00:11:37 +0200 Subject: [PATCH 108/193] Added LlamaLab Automate notify platform (#2863) * Addod LlamaLab Automate notify platform * Added platform to .coveragerc * Added device-option and switched to voluptuous * Fixed voluptuous usage --- .coveragerc | 1 + .../components/notify/llamalab_automate.py | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 homeassistant/components/notify/llamalab_automate.py diff --git a/.coveragerc b/.coveragerc index f68872401c2..06e35d9b0bc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -183,6 +183,7 @@ omit = homeassistant/components/notify/group.py homeassistant/components/notify/instapush.py homeassistant/components/notify/joaoapps_join.py + homeassistant/components/notify/llamalab_automate.py homeassistant/components/notify/message_bird.py homeassistant/components/notify/nma.py homeassistant/components/notify/pushbullet.py diff --git a/homeassistant/components/notify/llamalab_automate.py b/homeassistant/components/notify/llamalab_automate.py new file mode 100644 index 00000000000..7a00b5ba237 --- /dev/null +++ b/homeassistant/components/notify/llamalab_automate.py @@ -0,0 +1,60 @@ +""" +LlamaLab Automate notification service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/notify.llamalab_automate/ +""" +import logging +import requests +import voluptuous as vol + +from homeassistant.components.notify import (BaseNotificationService, + PLATFORM_SCHEMA) +from homeassistant.const import CONF_API_KEY +from homeassistant.helpers import config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +CONF_TO = 'to' +CONF_DEVICE = 'device' +_RESOURCE = 'https://llamalab.com/automate/cloud/message' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Required(CONF_TO): cv.string, + vol.Optional(CONF_DEVICE): cv.string, +}) + + +def get_service(hass, config): + """Get the LlamaLab Automate notification service.""" + secret = config.get(CONF_API_KEY) + recipient = config.get(CONF_TO) + device = config.get(CONF_DEVICE) + + return AutomateNotificationService(secret, recipient, device) + + +# pylint: disable=too-few-public-methods +class AutomateNotificationService(BaseNotificationService): + """Implement the notification service for LlamaLab Automate.""" + + def __init__(self, secret, recipient, device=None): + """Initialize the service.""" + self._secret = secret + self._recipient = recipient + self._device = device + + def send_message(self, message="", **kwargs): + """Send a message to a user.""" + _LOGGER.debug("Sending to: %s, %s", self._recipient, str(self._device)) + data = { + "secret": self._secret, + "to": self._recipient, + "device": self._device, + "payload": message, + } + + response = requests.post(_RESOURCE, json=data) + if response.status_code != 200: + _LOGGER.error("Error sending message: " + str(response)) From 3fae4fefbfa82e600bfec208af1000f34b0b357b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 20 Aug 2016 15:14:57 -0700 Subject: [PATCH 109/193] Bust cache for new media player covers (#2882) --- .../components/media_player/__init__.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 38e476c5d8c..5448671b14d 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -4,6 +4,7 @@ Component to interface with various media players. For more details about this component, please refer to the documentation at https://home-assistant.io/components/media_player/ """ +import hashlib import logging import os import requests @@ -32,7 +33,7 @@ SCAN_INTERVAL = 10 ENTITY_ID_FORMAT = DOMAIN + '.{}' -ENTITY_IMAGE_URL = '/api/media_player_proxy/{0}?token={1}' +ENTITY_IMAGE_URL = '/api/media_player_proxy/{0}?token={1}&cache={2}' SERVICE_PLAY_MEDIA = 'play_media' SERVICE_SELECT_SOURCE = 'select_source' @@ -645,8 +646,17 @@ class MediaPlayerDevice(Entity): @property def entity_picture(self): """Return image of the media playing.""" - return None if self.state == STATE_OFF else \ - ENTITY_IMAGE_URL.format(self.entity_id, self.access_token) + if self.state == STATE_OFF: + return None + + url = self.media_image_url + + if url is None: + return None + + return ENTITY_IMAGE_URL.format( + self.entity_id, self.access_token, + hashlib.md5(url.encode('utf-8')).hexdigest()[:5]) @property def state_attributes(self): From 502c65ca326c0e8e60e13cc2b429b7101b682c01 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 21 Aug 2016 00:25:11 +0200 Subject: [PATCH 110/193] Migrate to voluptuous (#2907) --- homeassistant/components/switch/dlink.py | 43 ++++++++++++------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/switch/dlink.py b/homeassistant/components/switch/dlink.py index 97e4ee9674f..b65c521bad5 100644 --- a/homeassistant/components/switch/dlink.py +++ b/homeassistant/components/switch/dlink.py @@ -6,42 +6,41 @@ https://home-assistant.io/components/switch.dlink/ """ import logging -from homeassistant.components.switch import DOMAIN, SwitchDevice +import voluptuous as vol + +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import ( CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME) -from homeassistant.helpers import validate_config +import homeassistant.helpers.config_validation as cv -# constants -DEFAULT_USERNAME = 'admin' -DEFAULT_PASSWORD = '' -DEVICE_DEFAULT_NAME = 'D-link Smart Plug W215' REQUIREMENTS = ['https://github.com/LinuxChristian/pyW215/archive/' 'v0.1.1.zip#pyW215==0.1.1'] -# setup logger _LOGGER = logging.getLogger(__name__) +DEFAULT_NAME = 'D-link Smart Plug W215' +DEFAULT_PASSWORD = '' +DEFAULT_USERNAME = 'admin' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string, + vol.Required(CONF_PASSWORD, default=DEFAULT_PASSWORD): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): - """Find and return D-Link Smart Plugs.""" +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup a D-Link Smart Plug.""" from pyW215.pyW215 import SmartPlug - # check for required values in configuration file - if not validate_config({DOMAIN: config}, - {DOMAIN: [CONF_HOST]}, - _LOGGER): - return False - host = config.get(CONF_HOST) - username = config.get(CONF_USERNAME, DEFAULT_USERNAME) - password = str(config.get(CONF_PASSWORD, DEFAULT_PASSWORD)) - name = config.get(CONF_NAME, DEVICE_DEFAULT_NAME) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + name = config.get(CONF_NAME) - add_devices_callback([SmartPlugSwitch(SmartPlug(host, - password, - username), - name)]) + add_devices([SmartPlugSwitch(SmartPlug(host, password, username), name)]) class SmartPlugSwitch(SwitchDevice): From 8fc27cbe43610ede777f684324595fcc1dad7c02 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 21 Aug 2016 00:28:26 +0200 Subject: [PATCH 111/193] Migrate to voluptuous (#2905) --- .../components/sensor/dte_energy_bridge.py | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/sensor/dte_energy_bridge.py b/homeassistant/components/sensor/dte_energy_bridge.py index deb04e12128..90b484f46dc 100644 --- a/homeassistant/components/sensor/dte_energy_bridge.py +++ b/homeassistant/components/sensor/dte_energy_bridge.py @@ -1,33 +1,48 @@ -"""Support for monitoring energy usage using the DTE energy bridge.""" +""" +Support for monitoring energy usage using the DTE energy bridge. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.dte_energy_bridge/ +""" import logging +import voluptuous as vol + from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import PLATFORM_SCHEMA +import homeassistant.helpers.config_validation as cv +from homeassistant.const import CONF_NAME _LOGGER = logging.getLogger(__name__) +CONF_IP_ADDRESS = 'ip' + +DEFAULT_NAME = 'Current Energy Usage' + ICON = 'mdi:flash' +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_IP_ADDRESS): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the DTE energy bridge sensor.""" - ip_address = config.get('ip') - if not ip_address: - _LOGGER.error( - "Configuration Error" - "'ip' of the DTE energy bridge is required") - return None - dev = [DteEnergyBridgeSensor(ip_address)] - add_devices(dev) + name = config.get(CONF_NAME) + ip_address = config.get(CONF_IP_ADDRESS) + + add_devices([DteEnergyBridgeSensor(ip_address, name)]) # pylint: disable=too-many-instance-attributes class DteEnergyBridgeSensor(Entity): - """Implementation of an DTE Energy Bridge sensor.""" + """Implementation of a DTE Energy Bridge sensor.""" - def __init__(self, ip_address): + def __init__(self, ip_address, name): """Initialize the sensor.""" self._url = "http://{}/instantaneousdemand".format(ip_address) - self._name = "Current Energy Usage" + self._name = name self._unit_of_measurement = "kW" self._state = None From e8c6e4d561dcac5f8803365a9f9dfa82f9e352e1 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 21 Aug 2016 00:40:16 +0200 Subject: [PATCH 112/193] Clean-up, ordering, constants, and extend of schema (#2903) * Clean-up, ordering, constants, and extend of schema * Put REQUIREMENTS back and re-add line breaks * Clean-up, ordering, constants, and extend of schema * Extend platform --- homeassistant/components/sensor/cpuspeed.py | 9 ++-- .../components/sensor/deutsche_bahn.py | 10 ++-- homeassistant/components/sensor/dweet.py | 10 ++-- homeassistant/components/sensor/fixer.py | 33 ++++++------- homeassistant/components/sensor/glances.py | 7 +-- .../components/sensor/google_travel_time.py | 22 ++++----- homeassistant/components/sensor/gpsd.py | 40 ++++++++-------- homeassistant/components/sensor/hp_ilo.py | 21 +++++---- homeassistant/components/sensor/imap.py | 20 ++++---- homeassistant/components/sensor/mfi.py | 9 ++-- homeassistant/components/sensor/mqtt.py | 9 ++-- homeassistant/components/sensor/nzbget.py | 11 ++--- .../components/sensor/openexchangerates.py | 9 ++-- homeassistant/components/sensor/plex.py | 43 +++++++++-------- homeassistant/components/sensor/sabnzbd.py | 13 +++-- homeassistant/components/sensor/snmp.py | 47 ++++++++++--------- .../sensor/swiss_hydrological_data.py | 13 +++-- .../sensor/swiss_public_transport.py | 15 +++--- .../components/sensor/systemmonitor.py | 4 +- homeassistant/components/sensor/time_date.py | 4 +- .../components/sensor/transmission.py | 7 ++- homeassistant/components/sensor/twitch.py | 14 +++--- homeassistant/components/sensor/worldclock.py | 6 +-- .../components/sensor/wunderground.py | 19 ++++---- homeassistant/components/sensor/yr.py | 16 +++---- homeassistant/components/sensor/yweather.py | 33 +++++++------ homeassistant/components/switch/mystrom.py | 12 ++--- .../components/switch/transmission.py | 4 +- 28 files changed, 232 insertions(+), 228 deletions(-) diff --git a/homeassistant/components/sensor/cpuspeed.py b/homeassistant/components/sensor/cpuspeed.py index 393c1cd7257..51a9226e1b0 100644 --- a/homeassistant/components/sensor/cpuspeed.py +++ b/homeassistant/components/sensor/cpuspeed.py @@ -15,18 +15,19 @@ from homeassistant.helpers.entity import Entity REQUIREMENTS = ['py-cpuinfo==0.2.3'] -DEFAULT_NAME = 'CPU speed' -ATTR_VENDOR = 'Vendor ID' +_LOGGER = logging.getLogger(__name__) + ATTR_BRAND = 'Brand' ATTR_HZ = 'GHz Advertised' +ATTR_VENDOR = 'Vendor ID' + +DEFAULT_NAME = 'CPU speed' ICON = 'mdi:pulse' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - # pylint: disable=unused-variable def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/deutsche_bahn.py b/homeassistant/components/sensor/deutsche_bahn.py index b358a4b975a..17c14bb5df1 100644 --- a/homeassistant/components/sensor/deutsche_bahn.py +++ b/homeassistant/components/sensor/deutsche_bahn.py @@ -17,20 +17,20 @@ import homeassistant.util.dt as dt_util REQUIREMENTS = ['schiene==0.17'] -CONF_START = 'from' +_LOGGER = logging.getLogger(__name__) + CONF_DESTINATION = 'to' +CONF_START = 'from' + ICON = 'mdi:train' -_LOGGER = logging.getLogger(__name__) +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_DESTINATION): cv.string, vol.Required(CONF_START): cv.string, }) -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Deutsche Bahn Sensor.""" diff --git a/homeassistant/components/sensor/dweet.py b/homeassistant/components/sensor/dweet.py index 503308ffb6f..8d731dc4084 100644 --- a/homeassistant/components/sensor/dweet.py +++ b/homeassistant/components/sensor/dweet.py @@ -20,9 +20,14 @@ from homeassistant.util import Throttle REQUIREMENTS = ['dweepy==0.2.0'] +_LOGGER = logging.getLogger(__name__) + CONF_DEVICE = 'device' + DEFAULT_NAME = 'Dweet.io Sensor' +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_DEVICE): cv.string, vol.Required(CONF_VALUE_TEMPLATE): cv.template, @@ -30,11 +35,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, }) -_LOGGER = logging.getLogger(__name__) - -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) - # pylint: disable=unused-variable, too-many-function-args def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/fixer.py b/homeassistant/components/sensor/fixer.py index 05f6003039e..8aa5002fbfa 100644 --- a/homeassistant/components/sensor/fixer.py +++ b/homeassistant/components/sensor/fixer.py @@ -9,7 +9,8 @@ from datetime import timedelta import voluptuous as vol -from homeassistant.const import (CONF_PLATFORM, CONF_NAME) +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv @@ -18,33 +19,33 @@ REQUIREMENTS = ['fixerio==0.1.1'] _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = "Exchange rate" -ICON = 'mdi:currency' - CONF_BASE = 'base' CONF_TARGET = 'target' -STATE_ATTR_BASE = 'Base currency' -STATE_ATTR_TARGET = 'Target currency' -STATE_ATTR_EXCHANGE_RATE = 'Exchange rate' +DEFAULT_BASE = 'USD' +DEFAULT_NAME = 'Exchange rate' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'fixer', - vol.Optional(CONF_BASE): cv.string, - vol.Optional(CONF_NAME): cv.string, - vol.Required(CONF_TARGET): cv.string, -}) +ICON = 'mdi:currency' -# Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(days=1) +STATE_ATTR_BASE = 'Base currency' +STATE_ATTR_EXCHANGE_RATE = 'Exchange rate' +STATE_ATTR_TARGET = 'Target currency' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_TARGET): cv.string, + vol.Optional(CONF_BASE, default=DEFAULT_BASE): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Fixer.io sensor.""" from fixerio import (Fixerio, exceptions) - name = config.get(CONF_NAME, DEFAULT_NAME) - base = config.get(CONF_BASE, 'USD') + name = config.get(CONF_NAME) + base = config.get(CONF_BASE) target = config.get(CONF_TARGET) try: diff --git a/homeassistant/components/sensor/glances.py b/homeassistant/components/sensor/glances.py index 12f8d46090a..51a8ac4d46f 100644 --- a/homeassistant/components/sensor/glances.py +++ b/homeassistant/components/sensor/glances.py @@ -17,9 +17,11 @@ from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv -DEFAULT_NAME = 'Glances' -DEFAULT_HOST = 'localhost' +_LOGGER = logging.getLogger(__name__) _RESOURCE = 'api/2/all' + +DEFAULT_HOST = 'localhost' +DEFAULT_NAME = 'Glances' DEFAULT_PORT = '61208' SENSOR_TYPES = { @@ -47,7 +49,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), }) -_LOGGER = logging.getLogger(__name__) # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) diff --git a/homeassistant/components/sensor/google_travel_time.py b/homeassistant/components/sensor/google_travel_time.py index d95f43d68ae..18a97b12910 100644 --- a/homeassistant/components/sensor/google_travel_time.py +++ b/homeassistant/components/sensor/google_travel_time.py @@ -20,19 +20,19 @@ import homeassistant.helpers.config_validation as cv import homeassistant.helpers.location as location import homeassistant.util.dt as dt_util -_LOGGER = logging.getLogger(__name__) - REQUIREMENTS = ['googlemaps==2.4.4'] -# Return cached results if last update was less then this time ago -MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5) +_LOGGER = logging.getLogger(__name__) + +CONF_DESTINATION = 'destination' +CONF_MODE = 'mode' +CONF_OPTIONS = 'options' +CONF_ORIGIN = 'origin' +CONF_TRAVEL_MODE = 'travel_mode' DEFAULT_NAME = 'Google Travel Time' -CONF_ORIGIN = 'origin' -CONF_DESTINATION = 'destination' -CONF_TRAVEL_MODE = 'travel_mode' -CONF_OPTIONS = 'options' -CONF_MODE = 'mode' + +MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5) ALL_LANGUAGES = ['ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'eu', 'fa', 'fi', 'fr', 'gl', 'gu', 'hi', 'hr', 'hu', 'id', @@ -41,10 +41,10 @@ ALL_LANGUAGES = ['ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'sr', 'sv', 'ta', 'te', 'th', 'tl', 'tr', 'uk', 'vi', 'zh-CN', 'zh-TW'] -TRANSIT_PREFS = ['less_walking', 'fewer_transfers'] -TRAVEL_MODE = ['driving', 'walking', 'bicycling', 'transit'] AVOID = ['tolls', 'highways', 'ferries', 'indoor'] +TRANSIT_PREFS = ['less_walking', 'fewer_transfers'] TRANSPORT_TYPE = ['bus', 'subway', 'train', 'tram', 'rail'] +TRAVEL_MODE = ['driving', 'walking', 'bicycling', 'transit'] TRAVEL_MODEL = ['best_guess', 'pessimistic', 'optimistic'] UNITS = ['metric', 'imperial'] diff --git a/homeassistant/components/sensor/gpsd.py b/homeassistant/components/sensor/gpsd.py index a466ff32f7d..a9f8245b738 100644 --- a/homeassistant/components/sensor/gpsd.py +++ b/homeassistant/components/sensor/gpsd.py @@ -8,39 +8,39 @@ import logging import voluptuous as vol +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + ATTR_LATITUDE, ATTR_LONGITUDE, STATE_UNKNOWN, CONF_HOST, CONF_PORT, + CONF_NAME) from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -from homeassistant.const import (ATTR_LATITUDE, ATTR_LONGITUDE, STATE_UNKNOWN, - CONF_HOST, CONF_PORT, CONF_PLATFORM, - CONF_NAME) REQUIREMENTS = ['gps3==0.33.2'] -DEFAULT_NAME = 'GPS' +_LOGGER = logging.getLogger(__name__) + +ATTR_CLIMB = 'climb' +ATTR_ELEVATION = 'elevation' +ATTR_GPS_TIME = 'gps_time' +ATTR_MODE = 'mode' +ATTR_SPEED = 'speed' + DEFAULT_HOST = 'localhost' +DEFAULT_NAME = 'GPS' DEFAULT_PORT = 2947 -ATTR_GPS_TIME = 'gps_time' -ATTR_ELEVATION = 'elevation' -ATTR_SPEED = 'speed' -ATTR_CLIMB = 'climb' -ATTR_MODE = 'mode' - -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'gpsd', - vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_HOST): cv.string, - vol.Optional(CONF_PORT): cv.string, +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) -_LOGGER = logging.getLogger(__name__) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the GPSD component.""" - name = config.get(CONF_NAME, DEFAULT_NAME) - host = config.get(CONF_HOST, DEFAULT_HOST) - port = config.get(CONF_PORT, DEFAULT_PORT) + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) # Will hopefully be possible with the next gps3 update # https://github.com/wadda/gps3/issues/11 diff --git a/homeassistant/components/sensor/hp_ilo.py b/homeassistant/components/sensor/hp_ilo.py index 49586e45d50..bc7afe1bf3c 100644 --- a/homeassistant/components/sensor/hp_ilo.py +++ b/homeassistant/components/sensor/hp_ilo.py @@ -1,27 +1,31 @@ """ Support for information from HP ILO sensors. -This allows monitoring of HP server information +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.sensor.hp_ilo/ """ import logging from datetime import timedelta import voluptuous as vol + from homeassistant.const import ( CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD, CONF_NAME, - CONF_MONITORED_VARIABLES, - STATE_ON, STATE_OFF) + CONF_MONITORED_VARIABLES, STATE_ON, STATE_OFF) from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['python-hpilo==3.8'] + _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = 'HP ILO' DEFAULT_PORT = 443 +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) + # Each sensor is defined as follows: 'Descriptive name', 'python-ilo function' SENSOR_TYPES = { 'server_name': ['Server Name', 'get_server_name'], @@ -43,14 +47,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_MONITORED_VARIABLES, default=['server_name']): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.positive_int, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): @@ -82,7 +83,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class HpIloSensor(Entity): - """Represents an HP ILO sensor.""" + """Representation a HP ILO sensor.""" def __init__(self, hp_ilo_data, sensor_type, client_name): """Initialize the sensor.""" @@ -167,4 +168,4 @@ class HpIloData(object): port=self._port) except (hpilo.IloError, hpilo.IloCommunicationError, hpilo.IloLoginFailed) as error: - raise ValueError("Unable to init HP ILO. - %s", error) + raise ValueError("Unable to init HP ILO, %s", error) diff --git a/homeassistant/components/sensor/imap.py b/homeassistant/components/sensor/imap.py index 9958ff5a36a..47a85cd582f 100644 --- a/homeassistant/components/sensor/imap.py +++ b/homeassistant/components/sensor/imap.py @@ -5,27 +5,25 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.imap/ """ import logging + import voluptuous as vol from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_NAME, CONF_PORT, CONF_USERNAME, CONF_PASSWORD) import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -ICON = 'mdi:email-outline' - -CONF_USER = "user" -CONF_PASSWORD = "password" CONF_SERVER = "server" -CONF_PORT = "port" -CONF_NAME = "name" DEFAULT_PORT = 993 +ICON = 'mdi:email-outline' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required('platform'): 'imap', +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME): cv.string, - vol.Required(CONF_USER): cv.string, + vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_SERVER): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, @@ -35,10 +33,10 @@ PLATFORM_SCHEMA = vol.Schema({ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the IMAP platform.""" sensor = ImapSensor(config.get(CONF_NAME, None), - config.get(CONF_USER), + config.get(CONF_USERNAME), config.get(CONF_PASSWORD), config.get(CONF_SERVER), - config.get(CONF_PORT, DEFAULT_PORT)) + config.get(CONF_PORT)) if sensor.connection: add_devices([sensor]) diff --git a/homeassistant/components/sensor/mfi.py b/homeassistant/components/sensor/mfi.py index 0af020de5f2..90d07811304 100644 --- a/homeassistant/components/sensor/mfi.py +++ b/homeassistant/components/sensor/mfi.py @@ -9,7 +9,8 @@ import logging import requests from homeassistant.components.sensor import DOMAIN -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS +from homeassistant.const import ( + CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, STATE_ON, STATE_OFF, CONF_HOST) from homeassistant.helpers import validate_config from homeassistant.helpers.entity import Entity @@ -17,8 +18,6 @@ REQUIREMENTS = ['mficlient==0.3.0'] _LOGGER = logging.getLogger(__name__) -STATE_ON = 'on' -STATE_OFF = 'off' DIGITS = { 'volts': 1, 'amps': 1, @@ -40,14 +39,14 @@ CONF_VERIFY_TLS = 'verify_tls' def setup_platform(hass, config, add_devices, discovery_info=None): """Setup mFi sensors.""" if not validate_config({DOMAIN: config}, - {DOMAIN: ['host', + {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, _LOGGER): _LOGGER.error('A host, username, and password are required') return False - host = config.get('host') + host = config.get(CONF_HOST) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) use_tls = bool(config.get(CONF_TLS, True)) diff --git a/homeassistant/components/sensor/mqtt.py b/homeassistant/components/sensor/mqtt.py index eaa856b010e..c3d4910b527 100644 --- a/homeassistant/components/sensor/mqtt.py +++ b/homeassistant/components/sensor/mqtt.py @@ -9,7 +9,8 @@ import logging import voluptuous as vol import homeassistant.components.mqtt as mqtt -from homeassistant.const import CONF_NAME, CONF_VALUE_TEMPLATE, STATE_UNKNOWN +from homeassistant.const import ( + CONF_NAME, CONF_VALUE_TEMPLATE, STATE_UNKNOWN, CONF_UNIT_OF_MEASUREMENT) from homeassistant.components.mqtt import CONF_STATE_TOPIC, CONF_QOS import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity @@ -19,8 +20,6 @@ _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['mqtt'] -CONF_UNIT_OF_MEASUREMENT = 'unit_of_measurement' - DEFAULT_NAME = "MQTT Sensor" PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({ @@ -30,9 +29,9 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({ # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup MQTT Sensor.""" - add_devices_callback([MqttSensor( + add_devices([MqttSensor( hass, config[CONF_NAME], config[CONF_STATE_TOPIC], diff --git a/homeassistant/components/sensor/nzbget.py b/homeassistant/components/sensor/nzbget.py index 6248b935c95..f7a13645c59 100644 --- a/homeassistant/components/sensor/nzbget.py +++ b/homeassistant/components/sensor/nzbget.py @@ -18,9 +18,13 @@ from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv +_LOGGER = logging.getLogger(__name__) + DEFAULT_NAME = 'NZBGet' DEFAULT_PORT = 6789 +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) + SENSOR_TYPES = { 'article_cache': ['ArticleCacheMB', 'Article Cache', 'MB'], 'average_download_rate': ['AverageDownloadRate', 'Average Speed', 'MB/s'], @@ -39,15 +43,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_USERNAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) - # pylint: disable=unused-argument, too-many-locals def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/openexchangerates.py b/homeassistant/components/sensor/openexchangerates.py index c7666b8ef80..b4e7033bcc0 100644 --- a/homeassistant/components/sensor/openexchangerates.py +++ b/homeassistant/components/sensor/openexchangerates.py @@ -16,14 +16,16 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -_RESOURCE = 'https://openexchangerates.org/api/latest.json' _LOGGER = logging.getLogger(__name__) +_RESOURCE = 'https://openexchangerates.org/api/latest.json' CONF_BASE = 'base' CONF_QUOTE = 'quote' -DEFAULT_NAME = 'Exchange Rate Sensor' DEFAULT_BASE = 'USD' +DEFAULT_NAME = 'Exchange Rate Sensor' + +MIN_TIME_BETWEEN_UPDATES = timedelta(hours=2) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_API_KEY): cv.string, @@ -32,9 +34,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(hours=2) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Open Exchange Rates sensor.""" diff --git a/homeassistant/components/sensor/plex.py b/homeassistant/components/sensor/plex.py index 62d60ff695f..7ead3175371 100644 --- a/homeassistant/components/sensor/plex.py +++ b/homeassistant/components/sensor/plex.py @@ -8,51 +8,58 @@ from datetime import timedelta import logging import voluptuous as vol -from homeassistant.const import (CONF_NAME, CONF_PLATFORM, CONF_USERNAME, - CONF_PASSWORD, CONF_HOST, CONF_PORT) +from homeassistant.components.switch import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_HOST, CONF_PORT) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['plexapi==2.0.2'] -CONF_SERVER = 'server' -MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1) - _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'plex', - vol.Optional(CONF_USERNAME): cv.string, +CONF_SERVER = 'server' + +DEFAULT_HOST = 'localhost' +DEFAULT_NAME = 'Plex' + +MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, - vol.Optional(CONF_SERVER): cv.string, - vol.Optional(CONF_NAME, default='Plex'): cv.string, - vol.Optional(CONF_HOST, default='localhost'): cv.string, vol.Optional(CONF_PORT, default=32400): cv.port, + vol.Optional(CONF_SERVER): cv.string, + vol.Optional(CONF_USERNAME): cv.string, }) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Demo sensors.""" + """Setup the Plex sensor.""" name = config.get(CONF_NAME) plex_user = config.get(CONF_USERNAME) plex_password = config.get(CONF_PASSWORD) plex_server = config.get(CONF_SERVER) plex_host = config.get(CONF_HOST) plex_port = config.get(CONF_PORT) - plex_url = 'http://' + plex_host + ':' + str(plex_port) - add_devices([PlexSensor(name, plex_url, plex_user, - plex_password, plex_server)]) + plex_url = 'http://{}:{}'.format(plex_host, plex_port) + + add_devices([PlexSensor( + name, plex_url, plex_user, plex_password, plex_server)]) class PlexSensor(Entity): - """Plex now playing sensor.""" + """Representation of a Plex now playing sensor.""" # pylint: disable=too-many-arguments def __init__(self, name, plex_url, plex_user, plex_password, plex_server): """Initialize the sensor.""" from plexapi.utils import NA + from plexapi.myplex import MyPlexAccount + from plexapi.server import PlexServer self._na_type = NA self._name = name @@ -60,12 +67,10 @@ class PlexSensor(Entity): self._now_playing = [] if plex_user and plex_password: - from plexapi.myplex import MyPlexAccount user = MyPlexAccount.signin(plex_user, plex_password) server = plex_server if plex_server else user.resources()[0].name self._server = user.resource(server).connect() else: - from plexapi.server import PlexServer self._server = PlexServer(plex_url) self.update() @@ -92,7 +97,7 @@ class PlexSensor(Entity): @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): - """Update method for plex sensor.""" + """Update method for Plex sensor.""" sessions = self._server.sessions() now_playing = [] for sess in sessions: diff --git a/homeassistant/components/sensor/sabnzbd.py b/homeassistant/components/sensor/sabnzbd.py index 48440f66790..a11d65d22bf 100644 --- a/homeassistant/components/sensor/sabnzbd.py +++ b/homeassistant/components/sensor/sabnzbd.py @@ -20,9 +20,14 @@ REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' 'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip' '#python-sabnzbd==0.1'] +_LOGGER = logging.getLogger(__name__) +_THROTTLED_REFRESH = None + DEFAULT_NAME = 'SABnzbd' DEFAULT_PORT = 8080 +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=1) + SENSOR_TYPES = { 'current_status': ['Status', None], 'speed': ['Speed', 'MB/s'], @@ -38,15 +43,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_MONITORED_VARIABLES, default=['current_status']): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) -_LOGGER = logging.getLogger(__name__) -_THROTTLED_REFRESH = None - -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=1) - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/snmp.py b/homeassistant/components/sensor/snmp.py index 59730624a11..f9f059c8f55 100644 --- a/homeassistant/components/sensor/snmp.py +++ b/homeassistant/components/sensor/snmp.py @@ -6,36 +6,39 @@ https://home-assistant.io/components/sensor.snmp/ """ import logging from datetime import timedelta + import voluptuous as vol +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity -from homeassistant.const import (CONF_HOST, CONF_PLATFORM, CONF_NAME, - CONF_PORT, ATTR_UNIT_OF_MEASUREMENT) +from homeassistant.const import ( + CONF_HOST, CONF_NAME, CONF_PORT, CONF_UNIT_OF_MEASUREMENT) +import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle REQUIREMENTS = ['pysnmp==4.3.2'] _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = "SNMP" -DEFAULT_COMMUNITY = "public" -DEFAULT_PORT = "161" -CONF_COMMUNITY = "community" -CONF_BASEOID = "baseoid" +CONF_BASEOID = 'baseoid' +CONF_COMMUNITY = 'community' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'snmp', - vol.Optional(CONF_NAME): vol.Coerce(str), - vol.Required(CONF_HOST): vol.Coerce(str), - vol.Optional(CONF_PORT): vol.Coerce(int), - vol.Optional(CONF_COMMUNITY): vol.Coerce(str), - vol.Required(CONF_BASEOID): vol.Coerce(str), - vol.Optional(ATTR_UNIT_OF_MEASUREMENT): vol.Coerce(str), -}) +DEFAULT_COMMUNITY = 'public' +DEFAULT_HOST = 'localhost' +DEFAULT_NAME = 'SNMP' +DEFAULT_PORT = '161' -# Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10) +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_BASEOID): cv.string, + vol.Optional(CONF_COMMUNITY, default=DEFAULT_COMMUNITY): cv.string, + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, +}) + # pylint: disable=too-many-locals def setup_platform(hass, config, add_devices, discovery_info=None): @@ -44,10 +47,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): UdpTransportTarget, ContextData, ObjectType, ObjectIdentity) + name = config.get(CONF_NAME) host = config.get(CONF_HOST) - port = config.get(CONF_PORT, DEFAULT_PORT) - community = config.get(CONF_COMMUNITY, DEFAULT_COMMUNITY) + port = config.get(CONF_PORT) + community = config.get(CONF_COMMUNITY) baseoid = config.get(CONF_BASEOID) + unit = config.get(CONF_UNIT_OF_MEASUREMENT) errindication, _, _, _ = next( getCmd(SnmpEngine(), @@ -61,9 +66,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False else: data = SnmpData(host, port, community, baseoid) - add_devices([SnmpSensor(data, - config.get('name', DEFAULT_NAME), - config.get('unit_of_measurement'))]) + add_devices([SnmpSensor(data, name, unit)]) class SnmpSensor(Entity): diff --git a/homeassistant/components/sensor/swiss_hydrological_data.py b/homeassistant/components/sensor/swiss_hydrological_data.py index 5c224f30d37..b2e95690727 100644 --- a/homeassistant/components/sensor/swiss_hydrological_data.py +++ b/homeassistant/components/sensor/swiss_hydrological_data.py @@ -10,8 +10,8 @@ from datetime import timedelta import voluptuous as vol import requests -from homeassistant.const import (TEMP_CELSIUS, CONF_PLATFORM, CONF_NAME, - STATE_UNKNOWN) +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (TEMP_CELSIUS, CONF_NAME, STATE_UNKNOWN) import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle @@ -21,8 +21,8 @@ REQUIREMENTS = ['xmltodict==0.10.2'] _LOGGER = logging.getLogger(__name__) _RESOURCE = 'http://www.hydrodata.ch/xml/SMS.xml' -DEFAULT_NAME = 'Water temperature' CONF_STATION = 'station' +DEFAULT_NAME = 'Water temperature' ICON = 'mdi:cup-water' ATTR_LOCATION = 'Location' @@ -36,10 +36,9 @@ ATTR_DISCHARGE_MAX = 'Discharge max' ATTR_WATERLEVEL_MAX = 'Level max' ATTR_TEMPERATURE_MAX = 'Temperature max' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'swiss_hydrological_data', - vol.Optional(CONF_NAME): cv.string, +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_STATION): vol.Coerce(int), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) # Return cached results if last scan was less then this time ago. @@ -50,8 +49,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Swiss hydrological sensor.""" import xmltodict + name = config.get(CONF_NAME) station = config.get(CONF_STATION) - name = config.get(CONF_NAME, DEFAULT_NAME) try: response = requests.get(_RESOURCE, timeout=5) diff --git a/homeassistant/components/sensor/swiss_public_transport.py b/homeassistant/components/sensor/swiss_public_transport.py index 0bfdc286bb6..d7d80ac2a3c 100644 --- a/homeassistant/components/sensor/swiss_public_transport.py +++ b/homeassistant/components/sensor/swiss_public_transport.py @@ -17,18 +17,22 @@ from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv +_LOGGER = logging.getLogger(__name__) _RESOURCE = 'http://transport.opendata.ch/v1/' -DEFAULT_NAME = 'Next Departure' ATTR_DEPARTURE_TIME1 = 'Next departure' ATTR_DEPARTURE_TIME2 = 'Next on departure' +ATTR_REMAINING_TIME = 'Remaining time' ATTR_START = 'Start' ATTR_TARGET = 'Destination' -ATTR_REMAINING_TIME = 'Remaining time' -CONF_START = 'from' + CONF_DESTINATION = 'to' +CONF_START = 'from' + +DEFAULT_NAME = 'Next Departure' ICON = 'mdi:bus' +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) TIME_STR_FORMAT = "%H:%M" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -37,11 +41,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) - def setup_platform(hass, config, add_devices, discovery_info=None): """Get the Swiss public transport sensor.""" diff --git a/homeassistant/components/sensor/systemmonitor.py b/homeassistant/components/sensor/systemmonitor.py index 0455ffb6428..893ec8154c4 100755 --- a/homeassistant/components/sensor/systemmonitor.py +++ b/homeassistant/components/sensor/systemmonitor.py @@ -17,6 +17,8 @@ import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['psutil==4.3.0'] +_LOGGER = logging.getLogger(__name__) + SENSOR_TYPES = { 'disk_use_percent': ['Disk Use', '%', 'mdi:harddisk'], 'disk_use': ['Disk Use', 'GiB', 'mdi:harddisk'], @@ -47,8 +49,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ })]) }) -_LOGGER = logging.getLogger(__name__) - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/time_date.py b/homeassistant/components/sensor/time_date.py index ea1b0c1e742..9281080b3b4 100644 --- a/homeassistant/components/sensor/time_date.py +++ b/homeassistant/components/sensor/time_date.py @@ -15,6 +15,8 @@ import homeassistant.util.dt as dt_util from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv +_LOGGER = logging.getLogger(__name__) + TIME_STR_FORMAT = "%H:%M" OPTION_TYPES = { @@ -31,8 +33,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.ensure_list, [vol.In(OPTION_TYPES)]), }) -_LOGGER = logging.getLogger(__name__) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Time and Date sensor.""" diff --git a/homeassistant/components/sensor/transmission.py b/homeassistant/components/sensor/transmission.py index e5ce3da235c..3c9aad05626 100644 --- a/homeassistant/components/sensor/transmission.py +++ b/homeassistant/components/sensor/transmission.py @@ -19,6 +19,9 @@ import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['transmissionrpc==0.11'] +_LOGGER = logging.getLogger(__name__) +_THROTTLED_REFRESH = None + DEFAULT_NAME = 'Transmission' DEFAULT_PORT = 9091 @@ -38,10 +41,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_USERNAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - -_THROTTLED_REFRESH = None - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/twitch.py b/homeassistant/components/sensor/twitch.py index 87bacbdafeb..73e2d221cb1 100644 --- a/homeassistant/components/sensor/twitch.py +++ b/homeassistant/components/sensor/twitch.py @@ -12,22 +12,24 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -CONF_CHANNELS = 'channels' -STATE_STREAMING = 'streaming' -STATE_OFFLINE = 'offline' +REQUIREMENTS = ['python-twitch==1.3.0'] + +_LOGGER = logging.getLogger(__name__) + ATTR_GAME = 'game' ATTR_TITLE = 'title' + +CONF_CHANNELS = 'channels' ICON = 'mdi:twitch' -REQUIREMENTS = ['python-twitch==1.3.0'] +STATE_OFFLINE = 'offline' +STATE_STREAMING = 'streaming' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_CHANNELS, default=[]): vol.All(cv.ensure_list, [cv.string]), }) -_LOGGER = logging.getLogger(__name__) - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/worldclock.py b/homeassistant/components/sensor/worldclock.py index 4eed783e510..43141b51b3d 100644 --- a/homeassistant/components/sensor/worldclock.py +++ b/homeassistant/components/sensor/worldclock.py @@ -14,7 +14,9 @@ import homeassistant.util.dt as dt_util from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -DEFAULT_NAME = "Worldclock Sensor" +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'Worldclock Sensor' ICON = 'mdi:clock' TIME_STR_FORMAT = "%H:%M" @@ -23,8 +25,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Worldclock sensor.""" diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 16672b03b4b..0321c4f7dcb 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -6,23 +6,23 @@ https://home-assistant.io/components/sensor.wunderground/ """ from datetime import timedelta import logging -import requests +import requests import voluptuous as vol +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle -from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS, - CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, - STATE_UNKNOWN) +from homeassistant.const import ( + CONF_MONITORED_CONDITIONS, CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS, + STATE_UNKNOWN) -CONF_PWS_ID = 'pws_id' _RESOURCE = 'http://api.wunderground.com/api/{}/conditions/q/' _LOGGER = logging.getLogger(__name__) -# Return cached results if last scan was less then this time ago. +CONF_PWS_ID = 'pws_id' + MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) # Sensor types are defined like: Name, units @@ -57,11 +57,10 @@ SENSOR_TYPES = { } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_PLATFORM): "wunderground", vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_PWS_ID): cv.string, - vol.Required(CONF_MONITORED_CONDITIONS, - default=[]): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Required(CONF_MONITORED_CONDITIONS, default=[]): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), }) diff --git a/homeassistant/components/sensor/yr.py b/homeassistant/components/sensor/yr.py index 3407838899e..d69bd65688a 100644 --- a/homeassistant/components/sensor/yr.py +++ b/homeassistant/components/sensor/yr.py @@ -9,17 +9,16 @@ import requests import voluptuous as vol import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ( - CONF_PLATFORM, CONF_LATITUDE, CONF_LONGITUDE, CONF_ELEVATION, - CONF_MONITORED_CONDITIONS -) + CONF_LATITUDE, CONF_LONGITUDE, CONF_ELEVATION, CONF_MONITORED_CONDITIONS) from homeassistant.helpers.entity import Entity from homeassistant.util import dt as dt_util -_LOGGER = logging.getLogger(__name__) - REQUIREMENTS = ['xmltodict==0.10.2'] +_LOGGER = logging.getLogger(__name__) + # Sensor types are defined like so: SENSOR_TYPES = { 'symbol': ['Symbol', None], @@ -38,8 +37,7 @@ SENSOR_TYPES = { 'dewpointTemperature': ['Dewpoint temperature', '°C'], } -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'yr', +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): [vol.In(SENSOR_TYPES.keys())], vol.Optional(CONF_LATITUDE): cv.latitude, @@ -58,9 +56,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("Latitude or longitude not set in Home Assistant config") return False - coordinates = dict(lat=latitude, - lon=longitude, - msl=elevation) + coordinates = dict(lat=latitude, lon=longitude, msl=elevation) weather = YrData(coordinates) diff --git a/homeassistant/components/sensor/yweather.py b/homeassistant/components/sensor/yweather.py index b0156497177..8e89b25282c 100644 --- a/homeassistant/components/sensor/yweather.py +++ b/homeassistant/components/sensor/yweather.py @@ -6,15 +6,25 @@ https://home-assistant.io/components/sensor.yweather/ """ import logging from datetime import timedelta + import voluptuous as vol -from homeassistant.const import (CONF_PLATFORM, TEMP_CELSIUS, - CONF_MONITORED_CONDITIONS, STATE_UNKNOWN) +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + TEMP_CELSIUS, CONF_MONITORED_CONDITIONS, STATE_UNKNOWN) +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle REQUIREMENTS = ["yahooweather==0.7"] +_LOGGER = logging.getLogger(__name__) + +CONF_FORECAST = 'forecast' +CONF_WOEID = 'woeid' + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) + SENSOR_TYPES = { 'weather_current': ['Current', None], 'weather': ['Condition', None], @@ -27,27 +37,22 @@ SENSOR_TYPES = { 'visibility': ['Visibility', "distance"], } -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): "yweather", - vol.Optional("woeid"): vol.Coerce(str), - vol.Optional("forecast"): vol.Coerce(int), +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_WOEID, default=None): cv.string, + vol.Optional(CONF_FORECAST, default=0): + vol.All(vol.Coerce(int), vol.Range(min=0, max=5)), vol.Required(CONF_MONITORED_CONDITIONS, default=[]): - [vol.In(SENSOR_TYPES.keys())], + [vol.In(SENSOR_TYPES)], }) -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) - -_LOGGER = logging.getLogger(__name__) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Yahoo! weather sensor.""" from yahooweather import get_woeid, UNIT_C, UNIT_F unit = hass.config.units.temperature_unit - woeid = config.get("woeid", None) - forecast = config.get("forecast", 0) + woeid = config.get(CONF_WOEID) + forecast = config.get(CONF_FORECAST) # convert unit yunit = UNIT_C if unit == TEMP_CELSIUS else UNIT_F diff --git a/homeassistant/components/switch/mystrom.py b/homeassistant/components/switch/mystrom.py index 867392e4661..2f8679fb209 100644 --- a/homeassistant/components/switch/mystrom.py +++ b/homeassistant/components/switch/mystrom.py @@ -8,9 +8,9 @@ import logging import voluptuous as vol -from homeassistant.const import (CONF_PLATFORM, CONF_NAME, CONF_HOST) +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_NAME, CONF_HOST) import homeassistant.helpers.config_validation as cv -from homeassistant.components.switch import SwitchDevice REQUIREMENTS = ['python-mystrom==0.3.6'] @@ -18,10 +18,9 @@ DEFAULT_NAME = 'myStrom Switch' _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): 'mystrom', - vol.Optional(CONF_NAME): cv.string, +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) @@ -29,6 +28,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Find and return myStrom switch.""" from pymystrom import MyStromPlug, exceptions + name = config.get(CONF_NAME) host = config.get(CONF_HOST) try: @@ -37,7 +37,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("No route to device '%s'", host) return False - add_devices([MyStromSwitch(config.get('name', DEFAULT_NAME), host)]) + add_devices([MyStromSwitch(name, host)]) class MyStromSwitch(SwitchDevice): diff --git a/homeassistant/components/switch/transmission.py b/homeassistant/components/switch/transmission.py index 0771724e0a3..6b8f89838d5 100644 --- a/homeassistant/components/switch/transmission.py +++ b/homeassistant/components/switch/transmission.py @@ -17,6 +17,8 @@ import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['transmissionrpc==0.11'] +_LOGGING = logging.getLogger(__name__) + DEFAULT_NAME = 'Transmission Turtle Mode' DEFAULT_PORT = 9091 @@ -28,8 +30,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_USERNAME): cv.string, }) -_LOGGING = logging.getLogger(__name__) - # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): From 18fd17fdf3fd05c3d16a16dd1f7c80fd9b02dca5 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 21 Aug 2016 00:41:14 +0200 Subject: [PATCH 113/193] Migrate to voluptuous (#2901) --- .../components/light/blinksticklight.py | 31 +++++++++++++------ requirements_all.txt | 2 +- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/light/blinksticklight.py b/homeassistant/components/light/blinksticklight.py index ad3bb2c6751..627097d47b9 100644 --- a/homeassistant/components/light/blinksticklight.py +++ b/homeassistant/components/light/blinksticklight.py @@ -6,26 +6,37 @@ https://home-assistant.io/components/light.blinksticklight/ """ import logging +import voluptuous as vol + from homeassistant.components.light import (ATTR_RGB_COLOR, SUPPORT_RGB_COLOR, - Light) + Light, PLATFORM_SCHEMA) +from homeassistant.const import CONF_NAME +import homeassistant.helpers.config_validation as cv + +CONF_SERIAL = 'serial' +DEFAULT_NAME = 'Blinkstick' +REQUIREMENTS = ["blinkstick==1.1.8"] +SUPPORT_BLINKSTICK = SUPPORT_RGB_COLOR + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_SERIAL): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ["blinkstick==1.1.7"] - - -SUPPORT_BLINKSTICK = SUPPORT_RGB_COLOR - - # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Add device specified by serial number.""" from blinkstick import blinkstick - stick = blinkstick.find_by_serial(config['serial']) + name = config.get(CONF_NAME) + serial = config.get(CONF_SERIAL) - add_devices_callback([BlinkStickLight(stick, config['name'])]) + stick = blinkstick.find_by_serial(serial) + + add_devices([BlinkStickLight(stick, name)]) class BlinkStickLight(Light): diff --git a/requirements_all.txt b/requirements_all.txt index 52825484870..5b346816455 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -35,7 +35,7 @@ apcaccess==0.0.4 astral==1.2 # homeassistant.components.light.blinksticklight -blinkstick==1.1.7 +blinkstick==1.1.8 # homeassistant.components.sensor.bitcoin blockchain==1.3.3 From b62c3ac56ca62c581c8028e2ec033dbfc0b37e08 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Sun, 21 Aug 2016 01:41:58 +0300 Subject: [PATCH 114/193] Update dht sensor dependency Adafruit_DHT to v1.3.0 (#2900) The repository already merged the pull request adding python3 support. root is no longer required to use the gpio. Signed-off-by: Roi Dayan --- homeassistant/components/sensor/dht.py | 6 +++--- requirements_all.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/dht.py b/homeassistant/components/sensor/dht.py index 170c63a2620..df0cb4d3b69 100644 --- a/homeassistant/components/sensor/dht.py +++ b/homeassistant/components/sensor/dht.py @@ -13,9 +13,9 @@ from homeassistant.util import Throttle from homeassistant.util.temperature import celsius_to_fahrenheit # Update this requirement to upstream as soon as it supports Python 3. -REQUIREMENTS = ['http://github.com/mala-zaba/Adafruit_Python_DHT/archive/' - '4101340de8d2457dd194bca1e8d11cbfc237e919.zip' - '#Adafruit_DHT==1.1.0'] +REQUIREMENTS = ['http://github.com/adafruit/Adafruit_Python_DHT/archive/' + '310c59b0293354d07d94375f1365f7b9b9110c7d.zip' + '#Adafruit_DHT==1.3.0'] _LOGGER = logging.getLogger(__name__) SENSOR_TYPES = { diff --git a/requirements_all.txt b/requirements_all.txt index 5b346816455..4ac074448a4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -113,7 +113,7 @@ heatmiserV3==0.9.1 hikvision==0.4 # homeassistant.components.sensor.dht -# http://github.com/mala-zaba/Adafruit_Python_DHT/archive/4101340de8d2457dd194bca1e8d11cbfc237e919.zip#Adafruit_DHT==1.1.0 +# http://github.com/adafruit/Adafruit_Python_DHT/archive/310c59b0293354d07d94375f1365f7b9b9110c7d.zip#Adafruit_DHT==1.3.0 # homeassistant.components.light.flux_led https://github.com/Danielhiversen/flux_led/archive/0.6.zip#flux_led==0.6 From 5f508b6afa31d56df20d60b30ac2cc359e3e7f43 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 21 Aug 2016 01:28:45 +0200 Subject: [PATCH 115/193] Use voluptuous for REST platforms (#2887) * Initial step to migrate to voluptuous * Migrate to voluptuous * Add schema for sensor_classes --- .../components/binary_sensor/__init__.py | 4 ++ .../components/binary_sensor/rest.py | 46 +++++++------ homeassistant/components/notify/rest.py | 65 +++++++++++-------- homeassistant/components/sensor/rest.py | 41 ++++++++---- homeassistant/components/switch/rest.py | 40 +++++++----- homeassistant/const.py | 2 + 6 files changed, 122 insertions(+), 76 deletions(-) diff --git a/homeassistant/components/binary_sensor/__init__.py b/homeassistant/components/binary_sensor/__init__.py index 18cb8ea0cb2..2f751683265 100644 --- a/homeassistant/components/binary_sensor/__init__.py +++ b/homeassistant/components/binary_sensor/__init__.py @@ -6,6 +6,8 @@ https://home-assistant.io/components/binary_sensor/ """ import logging +import voluptuous as vol + from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import Entity from homeassistant.const import (STATE_ON, STATE_OFF) @@ -33,6 +35,8 @@ SENSOR_CLASSES = [ 'vibration', # On means vibration detected, Off means no vibration ] +SENSOR_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(SENSOR_CLASSES)) + def setup(hass, config): """Track states and offer events for binary sensors.""" diff --git a/homeassistant/components/binary_sensor/rest.py b/homeassistant/components/binary_sensor/rest.py index d9a6f1d8947..4a6e48ca5a3 100644 --- a/homeassistant/components/binary_sensor/rest.py +++ b/homeassistant/components/binary_sensor/rest.py @@ -6,30 +6,42 @@ https://home-assistant.io/components/binary_sensor.rest/ """ import logging -from homeassistant.components.binary_sensor import (BinarySensorDevice, - SENSOR_CLASSES) +import voluptuous as vol + +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA) from homeassistant.components.sensor.rest import RestData -from homeassistant.const import CONF_VALUE_TEMPLATE +from homeassistant.const import ( + CONF_PAYLOAD, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_METHOD, CONF_RESOURCE, + CONF_SENSOR_CLASS) from homeassistant.helpers import template +import homeassistant.helpers.config_validation as cv + +DEFAULT_METHOD = 'GET' +DEFAULT_NAME = 'REST Binary Sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PAYLOAD): cv.string, + vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_VALUE_TEMPLATE): cv.template, +}) _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = 'REST Binary Sensor' -DEFAULT_METHOD = 'GET' - # pylint: disable=unused-variable def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the REST binary sensor.""" - resource = config.get('resource', None) - method = config.get('method', DEFAULT_METHOD) - payload = config.get('payload', None) + name = config.get(CONF_NAME) + resource = config.get(CONF_RESOURCE) + method = config.get(CONF_METHOD) + payload = config.get(CONF_PAYLOAD) verify_ssl = config.get('verify_ssl', True) - - sensor_class = config.get('sensor_class') - if sensor_class not in SENSOR_CLASSES: - _LOGGER.warning('Unknown sensor class: %s', sensor_class) - sensor_class = None + sensor_class = config.get(CONF_SENSOR_CLASS) + value_template = config.get(CONF_VALUE_TEMPLATE) rest = RestData(method, resource, payload, verify_ssl) rest.update() @@ -39,11 +51,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False add_devices([RestBinarySensor( - hass, - rest, - config.get('name', DEFAULT_NAME), - sensor_class, - config.get(CONF_VALUE_TEMPLATE))]) + hass, rest, name, sensor_class, value_template)]) # pylint: disable=too-many-arguments diff --git a/homeassistant/components/notify/rest.py b/homeassistant/components/notify/rest.py index 6c913f4f639..5cc556a1957 100644 --- a/homeassistant/components/notify/rest.py +++ b/homeassistant/components/notify/rest.py @@ -1,5 +1,5 @@ """ -REST platform for notify component. +RESTful platform for notify component. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/notify.rest/ @@ -7,45 +7,56 @@ https://home-assistant.io/components/notify.rest/ import logging import requests +import voluptuous as vol from homeassistant.components.notify import ( - ATTR_TARGET, ATTR_TITLE, DOMAIN, BaseNotificationService) -from homeassistant.helpers import validate_config + ATTR_TARGET, ATTR_TITLE, BaseNotificationService, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_RESOURCE, CONF_METHOD, CONF_NAME) +import homeassistant.helpers.config_validation as cv + +CONF_MESSAGE_PARAMETER_NAME = 'message_param_name' +CONF_TARGET_PARAMETER_NAME = 'target_param_name' +CONF_TITLE_PARAMETER_NAME = 'title_param_name' +DEFAULT_MESSAGE_PARAM_NAME = 'message' +DEFAULT_METHOD = 'GET' +DEFAULT_TARGET_PARAM_NAME = None +DEFAULT_TITLE_PARAM_NAME = None + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_MESSAGE_PARAMETER_NAME, + default=DEFAULT_MESSAGE_PARAM_NAME): cv.string, + vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): + vol.In(['POST', 'GET', 'POST_JSON']), + vol.Optional(CONF_NAME): cv.string, + vol.Optional(CONF_TARGET_PARAMETER_NAME, + default=DEFAULT_TARGET_PARAM_NAME): cv.string, + vol.Optional(CONF_TITLE_PARAMETER_NAME, + default=DEFAULT_TITLE_PARAM_NAME): cv.string, +}) _LOGGER = logging.getLogger(__name__) -DEFAULT_METHOD = 'GET' -DEFAULT_MESSAGE_PARAM_NAME = 'message' -DEFAULT_TITLE_PARAM_NAME = None -DEFAULT_TARGET_PARAM_NAME = None - def get_service(hass, config): - """Get the REST notification service.""" - if not validate_config({DOMAIN: config}, - {DOMAIN: ['resource', ]}, - _LOGGER): - return None + """Get the RESTful notification service.""" + resource = config.get(CONF_RESOURCE) + method = config.get(CONF_METHOD) + message_param_name = config.get(CONF_MESSAGE_PARAMETER_NAME) + title_param_name = config.get(CONF_TITLE_PARAMETER_NAME) + target_param_name = config.get(CONF_TARGET_PARAMETER_NAME) - method = config.get('method', DEFAULT_METHOD) - message_param_name = config.get('message_param_name', - DEFAULT_MESSAGE_PARAM_NAME) - title_param_name = config.get('title_param_name', - DEFAULT_TITLE_PARAM_NAME) - target_param_name = config.get('target_param_name', - DEFAULT_TARGET_PARAM_NAME) - - return RestNotificationService(config['resource'], method, - message_param_name, title_param_name, - target_param_name) + return RestNotificationService( + resource, method, message_param_name, title_param_name, + target_param_name) # pylint: disable=too-few-public-methods, too-many-arguments class RestNotificationService(BaseNotificationService): - """Implement the notification service for REST.""" + """Implementation of a notification service for REST.""" - def __init__(self, resource, method, message_param_name, - title_param_name, target_param_name): + def __init__(self, resource, method, message_param_name, title_param_name, + target_param_name): """Initialize the service.""" self._resource = resource self._method = method.upper() diff --git a/homeassistant/components/sensor/rest.py b/homeassistant/components/sensor/rest.py index 3f594c07234..022477d77a9 100644 --- a/homeassistant/components/sensor/rest.py +++ b/homeassistant/components/sensor/rest.py @@ -1,41 +1,56 @@ """ -Support for REST API sensors.. +Support for REST API sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.rest/ """ import logging +import voluptuous as vol import requests -from homeassistant.const import CONF_VALUE_TEMPLATE, STATE_UNKNOWN +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_PAYLOAD, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_METHOD, CONF_RESOURCE, + CONF_UNIT_OF_MEASUREMENT, STATE_UNKNOWN) from homeassistant.helpers.entity import Entity from homeassistant.helpers import template +import homeassistant.helpers.config_validation as cv + +DEFAULT_METHOD = 'GET' +DEFAULT_NAME = 'REST Sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PAYLOAD): cv.string, + vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, + vol.Optional(CONF_VALUE_TEMPLATE): cv.template, +}) _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = 'REST Sensor' -DEFAULT_METHOD = 'GET' - # pylint: disable=unused-variable def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the REST sensor.""" - resource = config.get('resource', None) - method = config.get('method', DEFAULT_METHOD) - payload = config.get('payload', None) + """Setup the RESTful sensor.""" + name = config.get(CONF_NAME) + resource = config.get(CONF_RESOURCE) + method = config.get(CONF_METHOD) + payload = config.get(CONF_PAYLOAD) verify_ssl = config.get('verify_ssl', True) + unit = config.get(CONF_UNIT_OF_MEASUREMENT) + value_template = config.get(CONF_VALUE_TEMPLATE) rest = RestData(method, resource, payload, verify_ssl) rest.update() if rest.data is None: - _LOGGER.error('Unable to fetch Rest data') + _LOGGER.error('Unable to fetch REST data') return False - add_devices([RestSensor( - hass, rest, config.get('name', DEFAULT_NAME), - config.get('unit_of_measurement'), config.get(CONF_VALUE_TEMPLATE))]) + add_devices([RestSensor(hass, rest, name, unit, value_template)]) # pylint: disable=too-many-arguments diff --git a/homeassistant/components/switch/rest.py b/homeassistant/components/switch/rest.py index d4c8ebe026d..ee29dd13adb 100644 --- a/homeassistant/components/switch/rest.py +++ b/homeassistant/components/switch/rest.py @@ -7,24 +7,35 @@ https://home-assistant.io/components/switch.rest/ import logging import requests +import voluptuous as vol -from homeassistant.components.switch import SwitchDevice +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_NAME, CONF_RESOURCE) +import homeassistant.helpers.config_validation as cv + +CONF_BODY_OFF = 'body_off' +CONF_BODY_ON = 'body_on' +DEFAULT_BODY_OFF = 'OFF' +DEFAULT_BODY_ON = 'ON' +DEFAULT_NAME = 'REST Switch' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_RESOURCE): cv.url, + vol.Optional(CONF_BODY_OFF, default=DEFAULT_BODY_OFF): cv.string, + vol.Optional(CONF_BODY_ON, default=DEFAULT_BODY_ON): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = "REST Switch" -DEFAULT_BODY_ON = "ON" -DEFAULT_BODY_OFF = "OFF" - # pylint: disable=unused-argument, def setup_platform(hass, config, add_devices_callback, discovery_info=None): - """Setup the REST switch.""" - resource = config.get('resource') - - if resource is None: - _LOGGER.error("Missing required variable: resource") - return False + """Setup the RESTful switch.""" + name = config.get(CONF_NAME) + resource = config.get(CONF_RESOURCE) + body_on = config.get(CONF_BODY_ON) + body_off = config.get(CONF_BODY_OFF) try: requests.get(resource, timeout=10) @@ -36,12 +47,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): _LOGGER.error("No route to resource/endpoint: %s", resource) return False - add_devices_callback([RestSwitch( - hass, - config.get('name', DEFAULT_NAME), - config.get('resource'), - config.get('body_on', DEFAULT_BODY_ON), - config.get('body_off', DEFAULT_BODY_OFF))]) + add_devices_callback([RestSwitch(hass, name, resource, body_on, body_off)]) # pylint: disable=too-many-arguments diff --git a/homeassistant/const.py b/homeassistant/const.py index d8c1f3d5a0d..13733d24e75 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -40,6 +40,7 @@ CONF_HOSTS = 'hosts' CONF_ICON = 'icon' CONF_LATITUDE = 'latitude' CONF_LONGITUDE = 'longitude' +CONF_METHOD = 'method' CONF_MONITORED_CONDITIONS = 'monitored_conditions' CONF_MONITORED_VARIABLES = 'monitored_variables' CONF_NAME = 'name' @@ -53,6 +54,7 @@ CONF_PORT = 'port' CONF_RESOURCE = 'resource' CONF_RESOURCES = 'resources' CONF_SCAN_INTERVAL = 'scan_interval' +CONF_SENSOR_CLASS = 'sensor_class' CONF_STATE = 'state' CONF_TEMPERATURE_UNIT = 'temperature_unit' CONF_TIME_ZONE = 'time_zone' From 46dcfb3d704a1f2369d19978641e451e1f77448d Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Sun, 21 Aug 2016 01:35:10 +0200 Subject: [PATCH 116/193] Serial CO2 sensor support (#2885) * Added support for serial HM-Z19 CO2 sensor * Minor pylint bug fixes * Added new files to .coveragerc * Removed newline * Changes in requirements after change of pmsensor library * Change the implementation of default name * Check if serial interface is working before adding the sensor * Maximum sensor value is 5000ppm --- .coveragerc | 1 + homeassistant/components/sensor/hmz19.py | 85 ++++++++++++++++++++++++ requirements_all.txt | 1 + 3 files changed, 87 insertions(+) create mode 100644 homeassistant/components/sensor/hmz19.py diff --git a/.coveragerc b/.coveragerc index 06e35d9b0bc..5bff9790325 100644 --- a/.coveragerc +++ b/.coveragerc @@ -216,6 +216,7 @@ omit = homeassistant/components/sensor/google_travel_time.py homeassistant/components/sensor/gpsd.py homeassistant/components/sensor/gtfs.py + homeassistant/components/sensor/hmz19.py homeassistant/components/sensor/hp_ilo.py homeassistant/components/sensor/imap.py homeassistant/components/sensor/lastfm.py diff --git a/homeassistant/components/sensor/hmz19.py b/homeassistant/components/sensor/hmz19.py new file mode 100644 index 00000000000..9cf3e4e4dd2 --- /dev/null +++ b/homeassistant/components/sensor/hmz19.py @@ -0,0 +1,85 @@ +""" +Support for CO2 sensor connected to a serial port. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.hmz19/ +""" +import logging +import voluptuous as vol + +from homeassistant.const import CONF_NAME +from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA + +REQUIREMENTS = ['pmsensor==0.3'] + + +_LOGGER = logging.getLogger(__name__) + +CONF_SERIAL_DEVICE = "serial_device" +DEFAULT_NAME = 'CO2 Sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_SERIAL_DEVICE): cv.string, +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the available CO2 sensors.""" + from pmsensor import co2sensor + + try: + co2sensor.read_mh_z19(config.get(CONF_SERIAL_DEVICE)) + except OSError as err: + _LOGGER.error("Could not open serial connection to %s (%s)", + config.get(CONF_SERIAL_DEVICE), err) + return False + + dev = HMZ19Sensor(config.get(CONF_SERIAL_DEVICE), config.get(CONF_NAME)) + add_devices([dev]) + + +class HMZ19Sensor(Entity): + """Representation of an CO2 sensor.""" + + def __init__(self, serial_device, name): + """Initialize a new PM sensor.""" + self._name = name + self._state = None + self._serial = serial_device + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + return "ppm" + + def update(self): + """Read from sensor and update the state.""" + from pmsensor import co2sensor + + _LOGGER.debug("Reading data from CO2 sensor") + try: + ppm = co2sensor.read_mh_z19(self._serial) + # values from sensor can only between 0 and 5000 + if (ppm >= 0) & (ppm <= 5000): + self._state = ppm + except OSError as err: + _LOGGER.error("Could not open serial connection to %s (%s)", + self._serial, err) + return + + def should_poll(self): + """Sensor needs polling.""" + return True diff --git a/requirements_all.txt b/requirements_all.txt index 4ac074448a4..85322e1ccf4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -254,6 +254,7 @@ pilight==0.0.2 # homeassistant.components.sensor.plex plexapi==2.0.2 +# homeassistant.components.sensor.hmz19 # homeassistant.components.sensor.serial_pm pmsensor==0.3 From 6aa0789e38e3d128477da33601511f7a5852b648 Mon Sep 17 00:00:00 2001 From: Heiko Rothe Date: Sun, 21 Aug 2016 05:49:38 +0200 Subject: [PATCH 117/193] MQTT room presence detection (#2913) * Added room presence tracker * Fixed room/device discovery bugs * Added tests for room tracker * Fixed some formatting mistakes * Fixed a tiny bug with the track new option * Converted device tracker into sensor * Removed leftover service entry * Changed name to mqtt_room * Changed payload validation to voluptuous * Fixed validation * Removed sleep from tests --- .coveragerc | 1 + homeassistant/components/sensor/mqtt_room.py | 139 +++++++++++++++++++ tests/components/sensor/test_mqtt_room.py | 107 ++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 homeassistant/components/sensor/mqtt_room.py create mode 100644 tests/components/sensor/test_mqtt_room.py diff --git a/.coveragerc b/.coveragerc index 5bff9790325..8a7da26d8ca 100644 --- a/.coveragerc +++ b/.coveragerc @@ -221,6 +221,7 @@ omit = homeassistant/components/sensor/imap.py homeassistant/components/sensor/lastfm.py homeassistant/components/sensor/loopenergy.py + homeassistant/components/sensor/mqtt_room.py homeassistant/components/sensor/neurio_energy.py homeassistant/components/sensor/nzbget.py homeassistant/components/sensor/ohmconnect.py diff --git a/homeassistant/components/sensor/mqtt_room.py b/homeassistant/components/sensor/mqtt_room.py new file mode 100644 index 00000000000..6980b7e6f7b --- /dev/null +++ b/homeassistant/components/sensor/mqtt_room.py @@ -0,0 +1,139 @@ +""" +Support for MQTT room presence detection. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.mqtt_room/ +""" +import logging +import json + +import voluptuous as vol + +import homeassistant.components.mqtt as mqtt +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME, STATE_UNKNOWN +from homeassistant.components.mqtt import CONF_STATE_TOPIC +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.util import dt, slugify + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['mqtt'] + +CONF_DEVICE_ID = 'device_id' +CONF_TIMEOUT = 'timeout' + +DEFAULT_TOPIC = 'room_presence' +DEFAULT_TIMEOUT = 5 +DEFAULT_NAME = 'Room Sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICE_ID): cv.string, + vol.Required(CONF_STATE_TOPIC, default=DEFAULT_TOPIC): cv.string, + vol.Required(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string +}) + +MQTT_PAYLOAD = vol.Schema(vol.All(json.loads, vol.Schema({ + vol.Required('id'): cv.string, + vol.Required('distance'): vol.Coerce(float) +}, extra=vol.ALLOW_EXTRA))) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup MQTT Sensor.""" + add_devices_callback([MQTTRoomSensor( + hass, + config.get(CONF_NAME), + config.get(CONF_STATE_TOPIC), + config.get(CONF_DEVICE_ID), + config.get(CONF_TIMEOUT) + )]) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class MQTTRoomSensor(Entity): + """Representation of a room sensor that is updated via MQTT.""" + + def __init__(self, hass, name, state_topic, device_id, timeout): + """Initialize the sensor.""" + self._state = STATE_UNKNOWN + self._hass = hass + self._name = name + self._state_topic = state_topic + '/+' + self._device_id = slugify(device_id).upper() + self._timeout = timeout + self._distance = None + self._updated = None + + def update_state(device_id, room, distance): + """Update the sensor state.""" + self._state = room + self._distance = distance + self._updated = dt.utcnow() + + self.update_ha_state() + + def message_received(topic, payload, qos): + """A new MQTT message has been received.""" + try: + data = MQTT_PAYLOAD(payload) + except vol.MultipleInvalid as error: + _LOGGER.debug('skipping update because of malformatted ' + 'data: %s', error) + return + + device = _parse_update_data(topic, data) + if device.get('device_id') == self._device_id: + if self._distance is None or self._updated is None: + update_state(**device) + else: + # update if: + # device is in the same room OR + # device is closer to another room OR + # last update from other room was too long ago + timediff = dt.utcnow() - self._updated + if device.get('room') == self._state \ + or device.get('distance') < self._distance \ + or timediff.seconds >= self._timeout: + update_state(**device) + + mqtt.subscribe(hass, self._state_topic, message_received, 1) + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return { + 'distance': self._distance + } + + @property + def state(self): + """Return the current room of the entity.""" + return self._state + + +def _parse_update_data(topic, data): + """Parse the room presence update.""" + parts = topic.split('/') + room = parts[-1] + device_id = slugify(data.get('id')).upper() + distance = data.get('distance') + parsed_data = { + 'device_id': device_id, + 'room': room, + 'distance': distance + } + return parsed_data diff --git a/tests/components/sensor/test_mqtt_room.py b/tests/components/sensor/test_mqtt_room.py new file mode 100644 index 00000000000..f5e9202234e --- /dev/null +++ b/tests/components/sensor/test_mqtt_room.py @@ -0,0 +1,107 @@ +"""The tests for the MQTT room presence sensor.""" +import json +import datetime +import unittest +from unittest.mock import patch + +import homeassistant.components.sensor as sensor +from homeassistant.components.mqtt import (CONF_STATE_TOPIC, CONF_QOS, + DEFAULT_QOS) +from homeassistant.const import (CONF_NAME, CONF_PLATFORM) +from homeassistant.util import dt + +from tests.common import ( + get_test_home_assistant, mock_mqtt_component, fire_mqtt_message) + +DEVICE_ID = '123TESTMAC' +NAME = 'test_device' +BEDROOM = 'bedroom' +LIVING_ROOM = 'living_room' + +BEDROOM_TOPIC = "room_presence/{}".format(BEDROOM) +LIVING_ROOM_TOPIC = "room_presence/{}".format(LIVING_ROOM) + +SENSOR_STATE = "sensor.{}".format(NAME) + +CONF_DEVICE_ID = 'device_id' +CONF_TIMEOUT = 'timeout' + +NEAR_MESSAGE = { + 'id': DEVICE_ID, + 'name': NAME, + 'distance': 1 +} + +FAR_MESSAGE = { + 'id': DEVICE_ID, + 'name': NAME, + 'distance': 10 +} + +REALLY_FAR_MESSAGE = { + 'id': DEVICE_ID, + 'name': NAME, + 'distance': 20 +} + + +class TestMQTTRoomSensor(unittest.TestCase): + """Test the room presence sensor.""" + + def setup_method(self, method): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + mock_mqtt_component(self.hass) + self.assertTrue(sensor.setup(self.hass, { + sensor.DOMAIN: { + CONF_PLATFORM: 'mqtt_room', + CONF_NAME: NAME, + CONF_DEVICE_ID: DEVICE_ID, + CONF_STATE_TOPIC: 'room_presence', + CONF_QOS: DEFAULT_QOS, + CONF_TIMEOUT: 5 + }})) + + # Clear state between tests + self.hass.states.set(SENSOR_STATE, None) + + def teardown_method(self, method): + """Stop everything that was started.""" + self.hass.stop() + + def send_message(self, topic, message): + """Test the sending of a message.""" + fire_mqtt_message( + self.hass, topic, json.dumps(message)) + self.hass.pool.block_till_done() + + def assert_state(self, room): + """Test the assertion of a room state.""" + state = self.hass.states.get(SENSOR_STATE) + self.assertEqual(state.state, room) + + def assert_distance(self, distance): + """Test the assertion of a distance state.""" + state = self.hass.states.get(SENSOR_STATE) + self.assertEqual(state.attributes.get('distance'), distance) + + def test_room_update(self): + """Test the updating between rooms.""" + self.send_message(BEDROOM_TOPIC, FAR_MESSAGE) + self.assert_state(BEDROOM) + self.assert_distance(10) + + self.send_message(LIVING_ROOM_TOPIC, NEAR_MESSAGE) + self.assert_state(LIVING_ROOM) + self.assert_distance(1) + + self.send_message(BEDROOM_TOPIC, FAR_MESSAGE) + self.assert_state(LIVING_ROOM) + self.assert_distance(1) + + time = dt.utcnow() + datetime.timedelta(seconds=7) + with patch('homeassistant.helpers.condition.dt_util.utcnow', + return_value=time): + self.send_message(BEDROOM_TOPIC, FAR_MESSAGE) + self.assert_state(BEDROOM) + self.assert_distance(10) From af22aeeba81f669781721dbbc9930a143fbf1ec8 Mon Sep 17 00:00:00 2001 From: "Teagan M. Glenn" Date: Sat, 20 Aug 2016 22:02:04 -0600 Subject: [PATCH 118/193] Apparently, doesn't load the root config secret --- homeassistant/util/yaml.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index ddbd70c4248..ddbc53b075c 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -170,8 +170,7 @@ def _secret_yaml(loader: SafeLineLoader, node: yaml.nodes.Node): """Load secrets and embed it into the configuration YAML.""" secret_path = os.path.dirname(loader.name) - while os.path.exists(secret_path) and not secret_path == os.path.dirname( - sys.path[0]): + while os.path.exists(secret_path): secrets = __SECRET_CACHE.get(secret_path, _load_secret_yaml(secret_path)) if node.value in secrets: @@ -180,7 +179,8 @@ def _secret_yaml(loader: SafeLineLoader, return secrets[node.value] next_path = os.path.dirname(secret_path) - if not next_path or next_path == secret_path: + if not next_path or next_path == secret_path \ + or secret_path == os.path.dirname(sys.path[0]): # Somehow we got past the .homeassistant configuration folder... break From aa6a0523ef60f299d9c22333fdfe52687e902ee4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 20 Aug 2016 23:04:55 -0700 Subject: [PATCH 119/193] Add template support to generic camera + local file tests (#2881) * Add template support to generic camera * Add tests for local file --- .coveragerc | 1 - homeassistant/components/camera/generic.py | 90 +++++++++----- homeassistant/components/camera/local_file.py | 40 +++--- tests/components/camera/test_generic.py | 115 ++++++++++++++++++ tests/components/camera/test_local_file.py | 69 +++++++++++ 5 files changed, 262 insertions(+), 53 deletions(-) create mode 100644 tests/components/camera/test_generic.py create mode 100644 tests/components/camera/test_local_file.py diff --git a/.coveragerc b/.coveragerc index 8a7da26d8ca..b0b7e63f043 100644 --- a/.coveragerc +++ b/.coveragerc @@ -106,7 +106,6 @@ omit = homeassistant/components/camera/bloomsky.py homeassistant/components/camera/ffmpeg.py homeassistant/components/camera/foscam.py - homeassistant/components/camera/generic.py homeassistant/components/camera/mjpeg.py homeassistant/components/camera/rpi_camera.py homeassistant/components/climate/eq3btsmart.py diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index 91712931c07..a03acc32eb8 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -8,23 +8,38 @@ import logging import requests from requests.auth import HTTPBasicAuth, HTTPDigestAuth +import voluptuous as vol + +from homeassistant.const import CONF_NAME, CONF_USERNAME, CONF_PASSWORD +from homeassistant.exceptions import TemplateError +from homeassistant.components.camera import PLATFORM_SCHEMA, Camera +from homeassistant.helpers import config_validation as cv, template -from homeassistant.components.camera import DOMAIN, Camera -from homeassistant.helpers import validate_config _LOGGER = logging.getLogger(__name__) +CONF_AUTHENTICATION = 'authentication' +CONF_STILL_IMAGE_URL = 'still_image_url' +CONF_LIMIT_REFETCH_TO_URL_CHANGE = 'limit_refetch_to_url_change' +DEFAULT_NAME = 'Generic Camera' BASIC_AUTHENTICATION = 'basic' DIGEST_AUTHENTICATION = 'digest' +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + # pylint: disable=no-value-for-parameter + vol.Required(CONF_STILL_IMAGE_URL): vol.Any(vol.Url(), cv.template), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_USERNAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_AUTHENTICATION, default=BASIC_AUTHENTICATION): + vol.In([BASIC_AUTHENTICATION, DIGEST_AUTHENTICATION]), + vol.Optional(CONF_LIMIT_REFETCH_TO_URL_CHANGE, default=False): cv.boolean, +}) + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Setup a generic IP Camera.""" - if not validate_config({DOMAIN: config}, {DOMAIN: ['still_image_url']}, - _LOGGER): - return None - add_devices_callback([GenericCamera(config)]) @@ -35,36 +50,47 @@ class GenericCamera(Camera): def __init__(self, device_info): """Initialize a generic camera.""" super().__init__() - self._name = device_info.get('name', 'Generic Camera') - self._authentication = device_info.get('authentication', - BASIC_AUTHENTICATION) - self._username = device_info.get('username') - self._password = device_info.get('password') - self._still_image_url = device_info['still_image_url'] + self._name = device_info.get(CONF_NAME) + self._still_image_url = device_info[CONF_STILL_IMAGE_URL] + self._limit_refetch = device_info[CONF_LIMIT_REFETCH_TO_URL_CHANGE] + + username = device_info.get(CONF_USERNAME) + password = device_info.get(CONF_PASSWORD) + + if username and password: + if device_info[CONF_AUTHENTICATION] == DIGEST_AUTHENTICATION: + self._auth = HTTPDigestAuth(username, password) + else: + self._auth = HTTPBasicAuth(username, password) + else: + self._auth = None + + self._last_url = None + self._last_image = None def camera_image(self): """Return a still image response from the camera.""" - if self._username and self._password: - if self._authentication == DIGEST_AUTHENTICATION: - auth = HTTPDigestAuth(self._username, self._password) - else: - auth = HTTPBasicAuth(self._username, self._password) - try: - response = requests.get( - self._still_image_url, - auth=auth, - timeout=10) - except requests.exceptions.RequestException as error: - _LOGGER.error('Error getting camera image: %s', error) - return None - else: - try: - response = requests.get(self._still_image_url, timeout=10) - except requests.exceptions.RequestException as error: - _LOGGER.error('Error getting camera image: %s', error) - return None + try: + url = template.render(self.hass, self._still_image_url) + except TemplateError as err: + _LOGGER.error('Error parsing template %s: %s', + self._still_image_url, err) + return self._last_image - return response.content + if url == self._last_url and self._limit_refetch: + return self._last_image + + kwargs = {'timeout': 10, 'auth': self._auth} + + try: + response = requests.get(url, **kwargs) + except requests.exceptions.RequestException as error: + _LOGGER.error('Error getting camera image: %s', error) + return None + + self._last_url = url + self._last_image = response.content + return self._last_image @property def name(self): diff --git a/homeassistant/components/camera/local_file.py b/homeassistant/components/camera/local_file.py index 463bf3eca5a..f7df934d9de 100644 --- a/homeassistant/components/camera/local_file.py +++ b/homeassistant/components/camera/local_file.py @@ -3,48 +3,48 @@ import logging import os -from homeassistant.components.camera import Camera +import voluptuous as vol + +from homeassistant.const import CONF_NAME +from homeassistant.components.camera import Camera, PLATFORM_SCHEMA +from homeassistant.helpers import config_validation as cv + +CONF_FILE_PATH = 'file_path' +DEFAULT_NAME = 'Local File' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_FILE_PATH): cv.isfile, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string +}) _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Camera.""" - # check for missing required configuration variable - if config.get("file_path") is None: - _LOGGER.error("Missing required variable: file_path") - return False - - setup_config = ( - { - "name": config.get("name", "Local File"), - "file_path": config.get("file_path") - } - ) + file_path = config[CONF_FILE_PATH] # check filepath given is readable - if not os.access(setup_config["file_path"], os.R_OK): + if not os.access(file_path, os.R_OK): _LOGGER.error("file path is not readable") return False - add_devices([ - LocalFile(setup_config) - ]) + add_devices([LocalFile(config[CONF_NAME], file_path)]) class LocalFile(Camera): """Local camera.""" - def __init__(self, device_info): + def __init__(self, name, file_path): """Initialize Local File Camera component.""" super().__init__() - self._name = device_info["name"] - self._config = device_info + self._name = name + self._file_path = file_path def camera_image(self): """Return image response.""" - with open(self._config["file_path"], 'rb') as file: + with open(self._file_path, 'rb') as file: return file.read() @property diff --git a/tests/components/camera/test_generic.py b/tests/components/camera/test_generic.py new file mode 100644 index 00000000000..f57ef62c0d4 --- /dev/null +++ b/tests/components/camera/test_generic.py @@ -0,0 +1,115 @@ +"""The tests for UVC camera module.""" +import unittest +from unittest import mock + +import requests_mock +from werkzeug.test import EnvironBuilder + +from homeassistant.bootstrap import setup_component +from homeassistant.components.http import request_class + +from tests.common import get_test_home_assistant + + +class TestGenericCamera(unittest.TestCase): + """Test the generic camera platform.""" + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.wsgi = mock.MagicMock() + self.hass.config.components.append('http') + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + @requests_mock.Mocker() + def test_fetching_url(self, m): + """Test that it fetches the given url.""" + self.hass.wsgi = mock.MagicMock() + m.get('http://example.com', text='hello world') + + assert setup_component(self.hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'generic', + 'still_image_url': 'http://example.com', + 'username': 'user', + 'password': 'pass' + }}) + + image_view = self.hass.wsgi.mock_calls[0][1][0] + + builder = EnvironBuilder(method='GET') + Request = request_class() + request = Request(builder.get_environ()) + request.authenticated = True + resp = image_view.get(request, 'camera.config_test') + + assert m.call_count == 1 + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello world' + + image_view.get(request, 'camera.config_test') + assert m.call_count == 2 + + @requests_mock.Mocker() + def test_limit_refetch(self, m): + """Test that it fetches the given url.""" + self.hass.wsgi = mock.MagicMock() + from requests.exceptions import Timeout + m.get('http://example.com/5a', text='hello world') + m.get('http://example.com/10a', text='hello world') + m.get('http://example.com/15a', text='hello planet') + m.get('http://example.com/20a', status_code=404) + + assert setup_component(self.hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'generic', + 'still_image_url': + 'http://example.com/{{ states.sensor.temp.state + "a" }}', + 'limit_refetch_to_url_change': True, + }}) + + image_view = self.hass.wsgi.mock_calls[0][1][0] + + builder = EnvironBuilder(method='GET') + Request = request_class() + request = Request(builder.get_environ()) + request.authenticated = True + + self.hass.states.set('sensor.temp', '5') + + with mock.patch('requests.get', side_effect=Timeout()): + resp = image_view.get(request, 'camera.config_test') + assert m.call_count == 0 + assert resp.status_code == 500, resp.response + + self.hass.states.set('sensor.temp', '10') + + resp = image_view.get(request, 'camera.config_test') + assert m.call_count == 1 + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello world' + + resp = image_view.get(request, 'camera.config_test') + assert m.call_count == 1 + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello world' + + self.hass.states.set('sensor.temp', '15') + + # Url change = fetch new image + resp = image_view.get(request, 'camera.config_test') + assert m.call_count == 2 + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello planet' + + # Cause a template render error + self.hass.states.remove('sensor.temp') + resp = image_view.get(request, 'camera.config_test') + assert m.call_count == 2 + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello planet' diff --git a/tests/components/camera/test_local_file.py b/tests/components/camera/test_local_file.py new file mode 100644 index 00000000000..d8ec570a8b0 --- /dev/null +++ b/tests/components/camera/test_local_file.py @@ -0,0 +1,69 @@ +"""The tests for UVC camera module.""" +from tempfile import NamedTemporaryFile +import unittest +from unittest import mock + +from werkzeug.test import EnvironBuilder + +from homeassistant.bootstrap import setup_component +from homeassistant.components.http import request_class + +from tests.common import get_test_home_assistant + + +class TestLocalCamera(unittest.TestCase): + """Test the generic camera platform.""" + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.hass.wsgi = mock.MagicMock() + self.hass.config.components.append('http') + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + def test_loading_file(self): + """Test that it loads image from disk.""" + self.hass.wsgi = mock.MagicMock() + + with NamedTemporaryFile() as fp: + fp.write('hello'.encode('utf-8')) + fp.flush() + + assert setup_component(self.hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'local_file', + 'file_path': fp.name, + }}) + + image_view = self.hass.wsgi.mock_calls[0][1][0] + + builder = EnvironBuilder(method='GET') + Request = request_class() + request = Request(builder.get_environ()) + request.authenticated = True + resp = image_view.get(request, 'camera.config_test') + + assert resp.status_code == 200, resp.response + assert resp.response[0].decode('utf-8') == 'hello' + + def test_file_not_readable(self): + """Test local file will not setup when file is not readable.""" + self.hass.wsgi = mock.MagicMock() + + with NamedTemporaryFile() as fp: + fp.write('hello'.encode('utf-8')) + fp.flush() + + with mock.patch('os.access', return_value=False): + assert setup_component(self.hass, 'camera', { + 'camera': { + 'name': 'config_test', + 'platform': 'local_file', + 'file_path': fp.name, + }}) + + assert [] == self.hass.states.all() From 23e86fc8eaddbea2a59a2fb06ee5d4e5a038f6d3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 20 Aug 2016 23:44:31 -0700 Subject: [PATCH 120/193] Update frontend --- homeassistant/components/climate/demo.py | 2 +- homeassistant/components/demo.py | 3 +-- homeassistant/components/frontend/version.py | 6 +++--- .../components/frontend/www_static/core.js | 8 ++++---- .../frontend/www_static/frontend.html | 4 ++-- .../frontend/www_static/frontend.html.gz | Bin 123194 -> 123558 bytes .../www_static/home-assistant-polymer | 2 +- .../components/frontend/www_static/mdi.html | 2 +- .../frontend/www_static/mdi.html.gz | Bin 171992 -> 174430 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2285 -> 2274 bytes 11 files changed, 14 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/climate/demo.py b/homeassistant/components/climate/demo.py index 445a568d2f0..340cc29f582 100644 --- a/homeassistant/components/climate/demo.py +++ b/homeassistant/components/climate/demo.py @@ -41,7 +41,7 @@ class DemoClimate(ClimateDevice): self._current_swing_mode = current_swing_mode self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"] self._operation_list = ["Heat", "Cool", "Auto Changeover", "Off"] - self._swing_list = ["Auto", 1, 2, 3, "Off"] + self._swing_list = ["Auto", "1", "2", "3", "Off"] @property def should_poll(self): diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index f083a96f5b2..863a2084892 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -19,9 +19,9 @@ COMPONENTS_WITH_DEMO_PLATFORM = [ 'alarm_control_panel', 'binary_sensor', 'camera', + 'climate', 'device_tracker', 'garage_door', - 'hvac', 'light', 'lock', 'media_player', @@ -29,7 +29,6 @@ COMPONENTS_WITH_DEMO_PLATFORM = [ 'rollershutter', 'sensor', 'switch', - 'thermostat', ] diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 82d10fb5f47..fbe60169862 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,9 +1,9 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "7a72f4dcf2a1d5e04094ef807478614d", - "frontend.html": "77a461848fe2a94da4e26a103bd6f814", - "mdi.html": "b399b5d3798f5b68b0a4fbaae3432d48", + "core.js": "b4ee3a700ef5549a36b436611e27d3a9", + "frontend.html": "203371247fdba69b4d4d92fd707a459a", + "mdi.html": "710b84acc99b32514f52291aba9cd8e8", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", "panels/ha-panel-dev-service.html": "bb5c587ada694e0fd42ceaaedd6fe6aa", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index 8b529c77424..4def07355e1 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&&"object"==typeof t&&"default"in t?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 De({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ce.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 Re({authToken:n,host:r})}function u(){return Le.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 Pe.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?Be({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||Be;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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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(n){}}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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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(c){throw A["default"].dispatchError(t,c.message),c}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var h="Store handler must return a value, did you forget a return statement";throw A["default"].dispatchError(t,h),new Error(h)}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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(o){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c199&&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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c \ No newline at end of file +var r=t.propertyDataFromStyles(n._styles,this),i=!this.__notStyleScopeCacheable;i&&(r.key.customStyle=this.customStyle,e=n._styleCache.retrieve(this.is,r.key,this._styles));var a=Boolean(e);a?this._styleProperties=e._styleProperties:this._computeStyleProperties(r.properties),this._computeOwnStyleProperties(),a||(e=o.retrieve(this.is,this._ownStyleProperties,this._styles));var l=Boolean(e)&&!a,h=this._applyStyleProperties(e);a||(h=h&&s?h.cloneNode(!0):h,e={style:h,_scopeSelector:this._scopeSelector,_styleProperties:this._styleProperties},i&&(r.key.customStyle={},this.mixin(r.key.customStyle,this.customStyle),n._styleCache.store(this.is,e,r.key,this._styles)),l||o.store(this.is,Object.create(e),this._ownStyleProperties,this._styles))},_computeStyleProperties:function(e){var n=this._findStyleHost();n._styleProperties||n._computeStyleProperties();var r=Object.create(n._styleProperties),s=t.hostAndRootPropertiesForScope(this);this.mixin(r,s.hostProps),e=e||t.propertyDataFromStyles(n._styles,this).properties,this.mixin(r,e),this.mixin(r,s.rootProps),t.mixinCustomStyle(r,this.customStyle),t.reify(r),this._styleProperties=r},_computeOwnStyleProperties:function(){for(var e,t={},n=0;n0&&l.push(t);return[{removed:a,added:l}]}},Polymer.Collection.get=function(e){return Polymer._collections.get(e)||new Polymer.Collection(e)},Polymer.Collection.applySplices=function(e,t){var n=Polymer._collections.get(e);return n?n._applySplices(t):null},Polymer({is:"dom-repeat",extends:"template",_template:null,properties:{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},sort:{type:Function,observer:"_sortChanged"},filter:{type:Function,observer:"_filterChanged"},observe:{type:String,observer:"_observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"_initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"_computeFrameTime(targetFramerate)"}},behaviors:[Polymer.Templatizer],observers:["_itemsChanged(items.*)"],created:function(){this._instances=[],this._pool=[],this._limit=1/0;var e=this;this._boundRenderChunk=function(){e._renderChunk()}},detached:function(){this.__isDetached=!0;for(var e=0;e=0;t--){var n=this._instances[t];n.isPlaceholder&&t=this._limit&&(n=this._downgradeInstance(t,n.__key__)),e[n.__key__]=t,n.isPlaceholder||n.__setProperty(this.indexAs,t,!0)}this._pool.length=0,this._setRenderedItemCount(this._instances.length),this.fire("dom-change"),this._tryRenderChunk()},_applyFullRefresh:function(){var e,t=this.collection;if(this._sortFn)e=t?t.getKeys():[];else{e=[];var n=this.items;if(n)for(var r=0;r=r;a--)this._detachAndRemoveInstance(a)},_numericSort:function(e,t){return e-t},_applySplicesUserSort:function(e){for(var t,n,r=this.collection,s={},i=0;i=0;i--){var h=a[i];void 0!==h&&this._detachAndRemoveInstance(h)}var c=this;if(l.length){this._filterFn&&(l=l.filter(function(e){return c._filterFn(r.getItem(e))})),l.sort(function(e,t){return c._sortFn(r.getItem(e),r.getItem(t))});var u=0;for(i=0;i>1,a=this._instances[o].__key__,l=this._sortFn(n.getItem(a),r);if(l<0)e=o+1;else{if(!(l>0)){i=o;break}s=o-1}}return i<0&&(i=s+1),this._insertPlaceholder(i,t),i},_applySplicesArrayOrder:function(e){for(var t,n=0;n=0?(e=this.as+"."+e.substring(n+1),i._notifyPath(e,t,!0)):i.__setProperty(this.as,t,!0))}},itemForElement:function(e){var t=this.modelForElement(e);return t&&t[this.as]},keyForElement:function(e){var t=this.modelForElement(e);return t&&t.__key__},indexForElement:function(e){var t=this.modelForElement(e);return t&&t[this.indexAs]}}),Polymer({is:"array-selector",_template:null,properties:{items:{type:Array,observer:"clearSelection"},multi:{type:Boolean,value:!1,observer:"clearSelection"},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}},clearSelection:function(){if(Array.isArray(this.selected))for(var e=0;e \ 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 e1c641e3169560539be5957dcd7cb747ecbc277d..85c93d71a4ccbb9b090dd983e6d6bdfa197f706c 100644 GIT binary patch delta 72439 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 hNEP=QKV?w8aF_m#=!sp delta 72204 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 Gl?MQrR7i9H diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 2c61fb2b72f..59627864944 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 2c61fb2b72f422155dac4e7308181f7f7f845f44 +Subproject commit 59627864944a93538858ed0930de92891b4bfe66 diff --git a/homeassistant/components/frontend/www_static/mdi.html b/homeassistant/components/frontend/www_static/mdi.html index 8bc5ae36aef..ff359e902b3 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 37bbb7ebf52308d3c733fd8e6d30fe1c5d3c84d4..d28209bbfee547ca69508030a228197455bcf095 100644 GIT binary patch delta 173191 zcmV(w)r6seD--cY~3{hV_HhzXQl4)0~P)k31f!^6X8zvH?8e*gUR z`0oD0)8otC>${h~eA+zTe!2VK|MunM{l9IH{eSNNtNrxx-+%t&-`msw`1g-@KfnCP zzkk}?fBfJ7cKhMO-OJ0nuTS@nukHEQ+t<&VmVJ!d8gB64E^M8@N!uJZ{-$m{{y4vD z|HW-i8$NY;>(hp>xVr7~A#FoMZc4kjE%nBwt@oRVcl6iqVyi6I4Ik%iE*rjs{|@JG zA6Xld2iC^tyMLDJoL=&ss%d}GsLsBi68frMc4*YDbYVVl|yJa+xo^&7r}_QXSLTE^E(*p+SUk#ufT z@Q(iaT|sT7Zuq<+#h38k;r#U@t7G!O>iB%uzSrAJE`M1)j?Hq(zM&%euHNMT2UW=b zcWqoku*SP$9dc})E7n<+VgD~}IbuC@KlvNK={DU>w{e)7@o$Xv_;*}B@BZ`OHvj8C z{{4S_T3e>?9`9cN`t;OPk$Tt0@n%lP0xzMwsI8O-yLR+zsrp+#*DSmmRdWLe+oBYG98!S zb^bJsf3|mz;ihkEWVHIYa3(pvt)6=7$A2rd-h_SM&ct?Vg-xrmHLX?jMmOI*eS3Yl zf4rMa8dr0F>f7gzs&e#=A8**M{Y6u7P_-0Whl8Q#ozw4>Z0A=SxxnPc)?}w&`TRT& zFP&W8<2|n4c9^!7wf}DL-+3b;0~>e#0LNxtzR(DYYvuWcYoqt!_W9$xk9V)P_kRyB zNSXr#jArUDt}?cV`7Ujbf+w`LtDs zF>HjB)^%#93x1YUJAT}@KY)}u70Y$q$+e2z$#ux#wO*a*mFjR)_V|xW7Kd8qdOojm zqf)ACZ(i0XCcKV*mGR1MqvmE$(|^_R`+WCda;dkQ_9v`^_V2tg+Rw6`XIFl5lGR@+ z*tc3+A97o5?Ha)DcVpt6=0SBK*>9u6w-0#Q zCaxaZ^!2sfK5aT27FTX#co^QjIvn@UA0F;zCw#lt{jOs1w?x|ozM{R=<9{m01>c3? zxbt=@c{`Q(yA{pDv6-;nva|PF2dq;23cl7)51}$Uz}(~jn?2=@^gr=V9gYD^(>Mbq zW<>`2yWK(=?QI)?#jcLh)8k)ecMM;`+6QHdt>fCHV5D!_4y*Zq>f)|P-y6}?rY51o zE^V;M+QjbLyKQ;2Il>W>L4PTFj!o4Ggt~QXc}y}$WE^Yp&6@3wgho1U~@JAbF#5r0RN5m(;j zXW*(j|BQ>L-4VMwVmcC6zb6e7lpxViKr|G~ZA}l_MtF@c`zftdrgYYrqG=?>?5VrD zb|0QT+`isFJx)dyI}`KRmX!`>Ba1YT+RDa}IU|1@_v$w6cx$!gkF!9YqdST^`7oqauL)fR6(VSV)D zDJI!e#y|Vf6!S)#J-t4~U%oxO-hZ7PkJ~(^>IGj){(SPxR=|~DWUNYc_GWU4K zX{3v(^{ge?w}@@lRyG+RF1NsYz3oD>a~n65Ilu0Dz3%$qQD?6gd)rO#?=rc+`^n8e zebzQBIk)lqbyB819#_zA)Y;Rkyv}(nS5`vch;lfyt%XD)rcH0V=jt%;VZ)+e)RWGr z1jZVCZ5!&sWq;YuY0m^}@DVkL)r^hdZoDPusNan0U<2H=A7$FhNvFH{Q;gee-2HUi z+v6ULZfbwY&E~cnJ0`o9wRL2J6SivQg^+Mvf&B#!T(@1?=s75oXsmCEW8 z8X`U#YoXh7pR^OQ`|iZ7@ea7l+Q0MON7Y7~jk1ysp?^tUTrZY}+jmCubv%1#Bwwd@ z7MbB%N#{vFOj}$REy>IF_N#@^+Pv0S=T@4KSK1n{lxr;oB?9`bC$%mfYT(bYpn3FF zJM?k7;35bV?PQ)ek?XqO44hYwOR`#~YR55UNqpc)5}e=k+ulCv&js5@lHSfkjrCli zyOdK>6@T*EJP>t;HEM}lER5MdQtIs(FI%2!S?~12xrYyQMTeXp9g==HCGoHfN20#? z-R1oC;eU>qf8H_EHx4$OhV!PS`j+*blV?Q|jBaXDE@C#)wOA9B$c@Bolt4iw*Nw6& zxo@nYIxg5z9_Jt^YVE?xrd+bmZB24)#S>v2gMY7dxcT&)3xk_wk3|8tXvWs|q_LLV zE=cuBR=HO2Dh2ZN^UvRr5<=KoIV*8Xv1?zjKOqEh5M>vLlF11dQ0MK`0L9Q)r8vk9 zw;ocq1NfcNNWI4If=S9AIXQ>~Wa1)2OklX|)JZsD3zZ_RmiFb+KG*e!h>t*Sei%M+ zlz%J|>{=n`#SIgrlYkta!pa1RFH2q>l$DDLn+#Mh4;0nQznR2j2Wg1(OM&#Y9VPxo zQ#vLP%alI!GvYGMADifvY@HZ%a&}vuW+7P;4Bpl?7OSEu?T(^wMO4`S5eGr~Cy?sTcVC|Va<|fv zp@HWnBf+jFjpax1gB*>VY zQw}Z%uVOf7;(-TKbZsk@Vp*=eZv_K{QSDu3u{M_D7xc+%L-cZY`~2baL_~*k=zk|8 z%Pwb11tl?3;h?eYD6CkBy4-Vs%nTe*+~fG8jI5o}2e5!0G3;2= z4Qt)-3vDBiM007@67sXNJhqta#@y=lX!M9QNR7_GLEgq>r|ga*LKW@wrEZt0DC{=r zT%y;VhWFCBHWiC{EAqST`r+YofTJdjI(8<6w$6)3==Ob?x0>ZlCXOr@FB^ITiZJp-^WBN|-&3 zkQm1{rMA0=?QVT*OQhpM>1h0rvI$U)dTnPq?IQ;2H<7*-{kP*{p%Sy;N`K`g#`BzH z8jqf$vvJVKb`;`fX+9xCrgpULldz+(T8d*(xRoO90+BXIX33?Q*OS!NYuKFLpOa1% zaBn)2`62E2S)?J6jobz8NTgmxNnXVs=ez1gGYUtdr;?WPJWJQzkf7wDH_>WP0orEt z2UXpU0o?2n=NhQzjT(Z}fqyqJ#Y)>0O$6)P`Ady5UiIovi05SMyQjPs!{K2Kfgx&H zu3$(#OG;DRv$B{E8fxFpp1RW%c&b4#FA2iqHcf3=dZ_X-F4Dn6eItEJ$7=C9j<7+r!=d;EV zRcnM%b@n#!NDmV-q<5C!)FB;gN>v548>m=zHHF{qwJeY0s~aSkbhjhg9lfSrq|o&-%oP+n<=0pFDG9b$sqfq3=1Wp9&nd_~$j(52RplV34%zuKiFkLJLE1cn7$xT#a z{m!`j_5O8ATY-++NwixxsvbL(7BD@iVz2}_C!E+#ii~CW)p&N;*L67VZffJN>rO)6 zx>0v{_FgKodh7{B$F<$`cr%X_HCS4gUv28gnj<%Rn9+gp+ij%AB|smJf7bcad?bsL zM?&k|lgY%vPk*gKfUpNfHYX+zJ!ql!%wAlK^~eA3+soW&=GW;c7iCx#$ig1y$A&C! zBT&uO5!o9)6Vps;sg0N{!uqiRBVW^Fuc`;GXR6cdCpx|P<2qI9t*|}!&rqIzyoUzr zZgM;&w6lXXT!CrZJ4dp(u?uaTQNrV~yeKWieRgBAy??ej8e8l^;P^~+Clpc{xjvd1 zMx%YGYo>8pzoS{GOmK=jY+cMYy!=mtPAo&HCwW{ zr8$|;)O;bC3#BYYhMklELRv+oAcVn*S9joXCczbmv_Sj4o>q7=g>0?n287fLTU@M; zLoW4ePJgFnpjIVg6S^LIk0zzC9FTDdWGs~ih;Ga0fyZWohPg(Q+x8TswITMqAZ;kL z!wFK6j9b2vv8j2dL=P?_L2Ktc1S*uB#P-l5KiHF9fo|W@^>8nZl$a_#BTF@5WU^S_Pdmb{Lj7I8?HP z6>FbM3q}H4pLQahJ*fg(Ig0f)#@BPfNpu@@+NSA;C{COXE_NK1fq11@H8{PC>c=|P z7k?}52-u7^Rn8jcXb{5V0iv?P1I3ZVEk@j9BZ(8pAewa0n4Tb$edVPKf)^_(+ffuC zrLz}F4i}j{bTn#}FuQ&57@^D8?;cB#B_yT5Ydiv3m(`9h4WG@%*N19vu!XEf4Ug8D z_K}ro|N3w{73rCDy)g)FbDqMC{v#9J+@xob?K2WJ6m+7m7Z*PaATCCrA0re7U~nP3{y5*$k2K299BfZ(JdyZZJC0p#1waJskYXEtnYCD zf_fFF_l;?bn@d;Lhvn~6D_aPDApFNA0o&1i7~8hOd@@fAQQO#M7=MI@Q_t%p zlSIaVj!jQs^*^zaMb(S;JlsBinNy10Px&TaZn`k~Njs|1&$@UFG7gfqMx$RE97aDy zXx?ixANg!NbLv|xEDBF&3l4VJ-ZvQ zihQ}Ow4S0#obeg64u3mEGHC5akc^d9t+M{eXHIgqX?E1{!q_r_YsnE_Kr~DV?J}yM zZhbxQ3gmS{w>(@FU>Zs|uX9iZbl!8gTOb>8Vp$qvRW-u7U)^In@r9mp>fkU~j)uQb zn=~c{%M?OikGnNc9+&am!qwbX>Cno5bblS!PKliv-9fU;+kY_1m5BBy?JTm^Kz0mf z-TeDTgVvK3V(!o=!U72lNfTs<{1X3>!Di`Y?Oe0ut?yQy*bA9!Z}J{SCNpCnLpP)s!%oeY)d zVvwlML2n=-Ab*@h8g;xhxO{m3ZBF}4jH;cR+FbL{9sdr?=VGZ74Z=vXTuj8woDIyO z86Z=@AqSm)5b^Yb)MhYO^Jj;l-rN_GUK;#?ekaM^a(L!WZQ;hYT*qw|E|x<0Npm8) z1hj?Jeyr9vcQI=R?$~0Q2g}6IN{R}%9~&Hoss9%ikAIreZbUXH4DHKW3pym$8?@qo z66hV_P?=T3I{LF&(;qk9)|^$#9mp?u)>(6qqr*?FW!rYV9{tAC7T`CEc}Ev`oY6ae zN-cGZ$17fj?BLUf*V|7ssnvAArAlk8Xv^N7g}WWqyYpN*w9j(`ey)|xuK4 z5B8jkk9_@nJN2HRy>r!?_ z;Exyq7^c=^j<_`3-tA;9%WRP>xm^P-Dc7N}BY#bUA&Q%xoH-6FrC_~Uy*P3xw5VId zS?DRRhA7bC+)MP#fX_dg*afu&H@nsL0bq?qu zjRFEH3GFwG4Qx7bcTkmI^WcP#Ou3p(dJb7jr3;x{=g-ETFn=^PDUv(0R~WJ@M;Jmz zT7R|4Bm6vVki-jX{RtGuGq+<>)~F=CSfB&-g&~eG z0rFCH#Wu#7R&a$vN_;CfGDOc%5xAWm)G=C`nxwZw~-@V>{xP6$pD34{!5XRwrjN=>S z1|-2)Dh~0_J{= z1w$g7eLQuYtlZl|ZB;K-dyOyta`!q_WHqMtL^WyHLz$RQ6!_kv5OJho(mLkwExBoRe==%YTg1lSq z<%KH4U^{+j9-paBij<*9Q7GrcM8CmcW)(2n@f7T}^DddO7|wXCeIc{7#hcBnC%|k! zn2^ts0h>d~&U8Ygyb5&8Je|nT7Jr^T4#Hk8ULVL@pR#m&o{$UlsPixthl-*tXjm}Q z{Gl&qUGAXGpo1i~i|G!jj$>xU)eTkErpoLsf{LURx^CcDTZ2?1uttaB0#YgAfCY1v z(7{ZfQXIo9=WsMbmr}8zTSM6oXjjnib{g?IptdD&9tx>`npr{B&2xx441bspVYN^$ zfpa+zDjzv1@B*SNp4vtOe<4??oAeB05GcW}Q43+uMRC+H;^1q`wcDAB2WEb-qUylm zE7^{0XaYU$L8&1svaZ&xk(H*2MHuq^RxV^bQ#0qCN?R|zW41ZPJDX8Mj?&8F;)Yu# znRaS;izg>f>tVm6`zruc%zqCTdWqrcj5{hCaPlYQa&4D(dT7D7qrIot7_vXittv=n zWy>^myK%?|hX(FE!DFIOMAHS@1UZ^9<-y#i-6NY(`{6{>ne7@lI;c3=o5~BX&kHHEfWdvxVuGnJI7p#D4e$}30dRa;JBq%c#GTzMMIx1=^`+p<-42-;>LPk@1 z4y;-mB^fE|gp8dsr6Dlja+IVN?Db1;)=!;xA0D2*ef;=*KQ(oZTy_qv?`_7Nr%MxM z5!f}-YJzIXxJNtMGl=NmS%4ImXEsX23mr*Bi6`Du-f?Z-kPylAY@*>GRrIo9>@Aa& zmE01FH7>i|Ic@nAC4YNLYpBtH9HnlV8#sr7cPQ@OYTER6CwpQiDBnv%+ZzT{f^8g+ zLK>Q(SRUTZJ2Omx5*}_;aB${!-N|M+Z)D+CHnKxY!X1i`JIbcm`ORghmoxPK+r#bS zhr78$a9OIQ$VBIPE{~B#*>tUJ0iRrTw9A?Zx~C|T9GM^^mVY15YxSkIPsb}I@nNWo zX*DIPVqyyfMeEFfrQO=2oHQ*UR`k@41Y8(xvT2M0w`6pyfDUPg{s|x^?ZTFXj93_r z3aLn@{Zga+UK$%p$@5qF~ID34O+1 zEsb8Ay0z4)Tg&3P!+4FG3&wofyE1XSnmt@nyN@3}KRquDxGw%{jkefanw_iP9noCj#GqNPmJ&Kkp-YD*>T}%)G-bRQM~C z&}RW>gq4(!gAg`>$BM+=ko`rU223lqf`X&gGPW{Fn$$?CA|bgt)2nl?pSt>)WMZ-~ z;SD(Y>E|;sd%9FZJbrwBy8k#cTqP9_Q+&*ABX*I7ff|O*6KVq_-_79i*9hm17U`A@ zWFJ{TK7Ru#-n=8a4dnm+l6HYb4m^|F>5)j76&k(J*#<}RMrJxtUrQ81b(arD=0X6P z@eV&mU^UgB@pwo&d!A4wTWG12hNlH!BCsIe5@n@QTh^%J8(^rl-9+z45`rZqtS_RSlq-w&-N(E4-#)#2|9t=P)7+=4PTfDt z^e~?sL23T99_!@&^7a8XeORHRBRXNAISQ@Ed>*t5k^1fqimgm0kA{z)jFlr^mcOBz z2!Gm%4T)SnCK-fxOr_E4>BYJDEL{dZxTE5df*MMd3Z`6lU?pQwl`9Rf1Ul!|(h_hd z8~7xDS8hTW)eXuADQ>B2!m_(IF)y#*KHfjgZS$}$BDK47%X<2|p6X$cTt!+42#SkR zzCaO?BNk3&589;2Cxcceqz-Es9MG~k41aV93Y=gbCq`DA&uR+hgVqxqs3%lmH0O2W zW}PI0w7-K4$z0G-pwO=#Zyjh~$-2V%1Az<}zKY(cOKowS`eoW=@LJ z5Ik#FM?h(wBr!SeT&xHOj&IT?i5&f&azeA;rHWiOtV(vQg~i%`hs&prlUt;l-hbx; zM4YODW=~gE#r>BB22Nw-c3${0-r!+?FBA8?c;dvj0C^}AtxsNQb5oN ziF7BCsWW&-QisF=^mrt0Yf#z?YRYr*(2%#~5R46FkbrAC`2*JD2bVyuwEYS}|8)-i zQpg$7W|%t@Y+Mv=NS3B2Oclh0gnw!fI~~lTz|k)|WTn}$IOKPhPjLphZ?Kv;KRZa5 z`6cXm${Hb0*-3EJSQhdlkRWe_5)^9V@p^D^jcLx<>xtNJ;O-N>A_3MjNS1<7^vLuR zlvl`V)pBVQn7Az|?oJf#B-EcM5iYXYc4TR2+eQXD5?GhVQJ_bP8*H+n)_=t4X^+Vt zs3W*;qA8s8^NDU&$`>AL5_?Yk5t{@kSb{`VaLA&|8rd^XDKcd-)G~Is*yXQAP*-*g zax6!mZI9vTxa&IfE1N_Mq9;1}!D(Ky3%m|-0YALDUf%tD|M+prbwnNlZBTa-9D6#U z1=>lP*cb=gL4F^Yh#lSPTYr*0^7xvNt-u#eMYyo$oGKRSzQ1>ZU8W@oBo;h9ZE zQ@14!V_!Zj(0kY|3R#45!BU`>Fen)3B!8+f%gMy|c|XAkqp$E-e<13P&8Vi?tzdqgl)7UKv5aqx?KrCx z(&M@y)jo}1LM=zC8WMVosy3hu* zlIf!vLU-VeK>Yq|(N@CZx-u;{`7Hs*1j`rGoG4i-6BOS`xmh((eG%hjpC*OUvo!i`P1CB2bu1D0bX+V>>X<&m_M&ggY`v#x zBja?laK6fSCx8C&_4(;xiqXrX(Ge}BP&yglp-Ak0_;7;JRu+}PR!# zIjIH-8^FtH7ljjtqA;M#0#_o_!gSwAdrU#ZGs>UhcfRxT`TpnE`BszgX4q@#yw`*b zQf#wDZZ?YjbPFg2pQ=;iLppue8yQFh6!`sD^2BVKFz{|bR*joa=L76!eg2S6@Q0l9iPS>G`b3++nd61?`)Cu&_BZ-1Zf-*CEg3sW1nFvoG5)gs4x9pxpLqQbTL)xZT0HxAgo_|Ju@|k z0)Gn<6i@4+07K|hWO*2<&`!ePrpGvJ_K3n)>F2i5(Mnk%lJ>4ZJE+=obkGsdo08;? zI+<;9jY(9T$SP$;RmnTk|1ev!&ID;P#;_{Arw`6f9yj*XQwx>otf#a9u7@=69UPUl zaDR)C-nH+;_`JPKf3O~^Iz!2U4LLCPw)NCm#yJ`N_X@c>*=?k9+xx{ElM zU8b!IRA<|M_FN2wYc#-euRlNEK7P7`4EFKUyPuz)|JtthDK5S@wTM4?+`4rAEsCWv zfUb4YNUgyBOsaoCPIW&*eB3heY>&dAAuKx%jqFPth zMphqxxqJNh?)~kDU;dH4sXt)qjUH{Sd-DUWbNI$e->g62=_8G~Z`$`sbN(5Zxeg6#xW7&V=6be*MFv6RnX`k z&ZgT3Nr?Cc*(rLG4yJ)EubvAMe5uudd&sIxW_;MniOcuOVsp&0{E*n>wk8f{W3K8G z9VET!uS`zWS<|w7d()bsJjdnz)9dTgmv;|$Gn%#X1R+LKz3C5GuDMb|3(z9(3rncv zo3%gRfBO77H4ta*bk0_&0e`Cs_mGlA9Wp?{Y z+;Tycom-~j!j`J%=FnAlXpeS_Hp!@m6cfhbv-Lb4+Arcj@1t!m za`^hhWn|99*9YX|(_iOs2AUJv&I(WhJ(E4LwhzsqfT39|uRj;0O?ABfskZ1IKF-7T z$oi7Y`KJEB=gy}B%}2lYwe@fpzayIfwlPa0cj5)plA^Nnk2UQYXlOpD+D?)dQq-#V z4`y^mKUevc>GSVSz<=kvzrp|DS9H@0TYjg%g+^*wX7dEuii}|v2;0*n z@h@@E2A4o5)ddBrbtvN~e8#)br3F>lm;r&%c`^e0dXOp`HmE`N@j(*$TsM3((MekM zQIVq0kk{3x*$@*B%e>y%bM*ksmO6&I%x;h$@Meql;KH4%p zfuWFdDm-#k_KnH<`26(skKHX006H$>`i$%b^eXL;4jZU_pL?kL(umyIrYN`Ku6?iVyo=RL*K-+<{9Ems zUyGL}jM^n!7k?VJ(XOnuiiS*my)^l#@^$D28`_`S31hVOdOz+nwPx}1!FuVm8No%_ zYg{@eiZ5P1dg-o6BfJxauvGP=uZ>1-D8D`?bGnQE2e@m?LBRJ6#UvFFuB<~e@=$pK z$57yuMh?<)>K%R>U&LU(u`Ox2*x zKIzE+v8Ju<{h``?x@Z(2!D6+)YX{cuyMOSu{9ZTTxE{aL&;Pj{|2elK=jzJs_xzlO%`*q=0@F24@`MceGizoR`KmX^{{pXyznyqWc?(eu^IdU0A{E1kN54hb$@C_&S=!OBu(`IwMKLbpwr9ab&xZ% z%=Nlgq>NTKB#E%UVGv*gA1-GBq&ssz>vezoI+Gkr0$3!I3KX1yUiK!4jTFR6z@)q~ z6a<9x=^DZO?dwu>McoN4oeyXE^Y^}XmMS~mY~T6Z6>j`jQ5VatKo9D(@WrKx^d6g-+d|6>LgjC8 z0@4KNM_O}DX!WZugXNX-d*H?VNY7qg?q6PKkopSMIzh<%bzxek5#>EWI(U8-p>t*f zi&aiya3N;Yt!OlYvC{U2maMJ7y#3RL%YT)QM)J81aZiewRS}c{4p;C)*$BaexK9XB zmMVR+_y|&$T{7qq0eI9QC`%x6hv4w*Mvj069Lvb4o(9%2UHtsA9I}P%Uh@Uny$gzI zGdSol4o(oVdlyE??tyOq<|fk9po4D3Jezvip$A&5$6(=NvOtO*F}`seZG`HZ7=LDc zXK?0xW<|5?C+Ma^)EIn-p4KNRv?+CrT$qds0Q@nzMg)r-z7ymz%%Jhu2~>;CbNm&D z$8iWr+?jc~yWt2g$$;0_+Yg_=+&wNLb+`3s(eFkFz_y=d($#!vkLqTIt33=6e)0;R zeRh0hebY>dI|bme)ms-w6~liSXMdT& z11;^T&TpF&w6Z@Gx@1t#m=E^GaoA;M4vI@J$#ww0O*IT#AyNkw^kp>L0-d$P`w-E1 zy&m;;*27-!X1yBqrXO_9{4Nj5KKspp9;`|K7kMf+!#NSL9 z!)ksn^f11>{5Y;fPEa7*6m*WTH$Iqabif05{m5p?Rwl`R(h&)9r)~SI8;gN=Y+($cD#|`Xlx_pgie#9k&pf zS6V-95#dgT+>KP>>=Gdi_AH*pG>*pIiA)Jlhh${Zn`m9?h_u$k=YPA$yT8sZ{RBV5 zbiNz^<>{WVFKuuw{_G#Tt6;3ELKV-nbD&s+Ya4{Hvc?amE=Q*U_%yrMrJo^^U zXMTZ>6Gh;`aO!C%n1A5P)muc=LU`Ezw|rmfdbJ;sv>#N6+aUd8rDt+ z3#kTj_&@+#;NG8rYQH1EI{-9~*0{Ar%!*Mi#Vj}9rLmQS3;$+ zEo`xO=71b&O@B|<#-fCS$~96tQunmghSSE*JU7gwy;n3C#e#?g?!j4PQ?MmEjYRRY z=;65F8$HQ@avR-0-~`F4ChCj>ef8)=tS7w!VGT$Yn#Tz=~L!_&u^96m8R>>hYTXdst9(1-{|)R8GV(Ly;<$+&N_T6dfEZsP`Q{2-MVhnrfBTKi|M~1_K4L9g3SdJz}#~KyxZscg7T9lkI zblxkF3XR-X=KuNO?(b8sD+B@GDULC(5`%m#VF=m|VT)NE1B)aW`nE9f;e;V8?Ja^? z0!?ja997o~{2m@85S$2Yva^`U43%IZm4EwUu#?r=~NC6ms27Hke)a&QpxLjk@+D1YKD zCe&W|G=V(~PA=hoa7h7Di)V;2@M-ikBKH>w=RkG~fpttK1Z<>@fEf|D){q8pa)0g= zX9%G@&j_4B%yzIIzy~EgO88CnzrYU_UBNo zaXWmozXWZ~7R^jR5Mk&ds1xfWPk(bqX}v#rS!=iCt`5(NS#zv_r3wFE`T$eZ_4!myZhoG0jhDwB8p;I1@ zr%XHv2Dd@r85Asx^v7V4g(N&4g2Mqa(M_@7+r^+x0zG#KKU^rhWZ=IWGC>S`+Z)(Y zHAHm*XDeE#lOyxa8Hjf9LjV;5YJ*_nuo0cp0%(#iD7~!>18N-tIe+&-!RwG;gp^I5 zLQ$e9Pu%P4*UO(GhaVkZQw# z$J;9`sQMzYSHafn*(?M>!Y+(LJp{lWWQp8x#z1#QBpVPqk5Qmjdy7>r1Z%==DWWDZ zZ5{6hdEW>rnc`-~cdrKMTjS;o?i)ODZv_p*D0zWX&-m)5bANTj$<5NWS|B}M28ON| zqa_e}Tij|f&-R{fv2tVcc_$ZH0tF55zQl9!a&2whL6O8F3hbT?4wkKt@< z7!U-5OBR{25<1@?k#aSMd^xnjbKiiJxFZv{DqQ}(f_oxN6C8~pMvZp6g>WOFXCTGh zkh_nOtReL_9)C$q46x*)#XiNEL?mAz2xUI+dnR|n?-_E#rGO7Z0n38!`-K@yL735YFOmPJ7Ru#ZF zfJS5hV*p)Mj35b7g|`A&R?h%wKpQGLdZPg@V3%fR(tlbh^BpGM2vUR-7PfYWl;Q`+ zyz_=tlzO2>K;FYZ_d3=#iWFdfgI9jY`puex7OU07Xvp4ht`O(UcKga*|I5_dy%&yj z#5oSFrfpPS_kzcQA0eZCIYn<|*!K~jp$Bpfg|HNI2z*&Vy0%hW0?X`dlF(>dnk10i zb-WP^=zrlz5qLyx6FgjkjRSkX^1}CY`twv%RG#k1+RJmuT-FJq+Yh!2nZSCAJItR) zMJk$d+x?8&&NFU%{yeM??z^Awr*0X63|-Ei{&lx_w$zBs%Ak zU!)!b`P6`U#IDJNf+N%w4iQLpGDSHRI%{|!(tokN4Q3e2m1S=Lz^~E3qU6D%#Re*v ziYbH;^_K(dgm2G*^+J$tJS31JGGPH==Z+Xy78)(?A%Q&Dvn%8C?QuCm8j(GP2f&sE zyW5}oqdwo~JTovMN!_0#2u3Iey|1iT}=;0q}4q z27ja5u~iJ>hbECl0qc*77B4zs0_IasUI?Bk2BRO1ONv(-`ObASyaVDc8rs31wb6dj z==|qzbXYXH|MNFGE*c&G{EhAxjSheQMyExi{hz(4k|daY2Dln{SfBOZ z=|;QqCyR;LWkfEb+kzAouqm`2I?{1*AJ%&4$MfOUc&{FYp@)oS1Y(UnjMl?A>fv&> z{145@j1cgFafr~FmN*H6-MWMf^{S&)1LCq_1K~Gv8^K9nUKHE+d>uV5%O0bGaet@r zd+2v>9WU1L%t!}OL6PIRq$S_%fA&An{~1l;1x}I_X6;`;e^=HPL&do7b}s(dGR5uw zC+hQeyOkDm=KkNAv+{#;R{vW~S^dFYmH!UC`f~p`3plO|WjEX}cH5Lu>t^3@b_tP3 zrf!*y9&WhnjdQy9;-1FKJ;Cx?QGdt?{5ih)m3BYgeY$;}VcVAj^H$@%8jr9Aj!1u~h={hWE(K@@T;_3z^$Wb*H5rpSwC1gngbw&8 zr|cFX>;LsDh^#4%))@xOoya~}EN|Jgpy<^eJ-yujDHj(boY4LxQ;%#*41Z|>rP<2+ z!8P~o@t4Or0NJ3h^@Mg&%uB~ZC()oIJ2O{sgF!=Q7M+cX*-502M>GIU13JEEO`g^x zgH3OAW{JpGH)c0xi5*>AN|o5ejwWpjXUexd@nnB8h@sgOZ!~DG*Al~ z-Ae@PRiAr-N=RKyeKwHC5k$0Y-k%zUf7XoTwlMO_9Q`u27&SQ7e(GSCr{Oq;$bn;o zV^>dk;@H=pLTiMgC7)ojM&u_)2y{2Ny$;cn8E&9Acj7F(rc=M#;MbQq(#^S_gSKS! zd-(^h51^Q1lvx(7@qTi6I^p6F4Ypy9^`ab`mzPGruqxo=qM&p&#y4LDl<= zXxbNxl~d`86Acz#t&-`4K@F$D6l!U-cQ+3Z1H}-NV?;$ zsXQYUvZ&aGHMBm# z--DCC(ESj+78KJk~rQnSdcNo*`|Rpzva6wUv9-K;3zvm=JHHS zO4Bhl5Baj-$ht^nG*c*dNa}-bRNm3&WZ;RZv{N9oo_~{~I8QJV${03UG!@#~d16r{ zo5;fGmyDsSTzKT%z+^`8nF@PKEpIhbh(gFY#@h1KLwgK`7DeWvUZi@Do6+PRwf-VZ zwv>eR46MF%z~j2fyclxWnY(8)>pmJ}WUg6=#$xNqi6=i)d$RhL;=Y(0SY~a>W>eqj z6&6{IV1F>~p*_cFQ5IqvRmhk@hU6NO*{so6j8RIf;(7(I^TSddPEguyDd<<*IB;`@ ziE4F-zDm@4KX6ERprF~x3ySj~Pg;*>#w=j!lVZiPNrG9qBNlI9FdpBXoV8=&Gp z+ES#!23Jv~AzjV_I@l>l8JB3?5@#WMv&5sxsegJ6TYFF=u)*5sN``qjcHw$LM$+*H=NL&N-Z@Wg}+@X=>D`K0GW>(?8OU|FXy4Gz27>~~K;|NQHkUKzL@ z2>b_{<<1*LPt?REouSbWbm%_>9AIs09cVd`sp41icM`oQs8kN&~2 z1Cw(oSj;f|+A$_#l*K#3S1A4$zqCG7tABjExk|KS00x;=%eh_7U~3Y?kBUQqK}*r- z;ASdDDf7mQMze#@I)!CuRXW(sGduWio$$(z>;Wq=N?MmIRtrOGII)aHo*@(WAi`z> zL1H^~6=%8CVOR(OI)<3&;Fzq3P zWNk+}4x`ke=V5^h79JT^AI#YJ5u&ofJePwI5M!j#1O4Xw{(oMZ$EzFNwl24Hyliyr zdF=gc!;vY(!x$VG(F_B_FbVy6``Z9sMil7mYt!P^ro~z8NlnXma)ycDy_= ziIzWFI_|P`Y@B!Fu^*=6JVS@eyzNG_Ii6!@v(E}Iv$nHoxXcSJ$l6hGp1I3xo@e;* z_N=`;+}(YhU1P2J1ZE)3D=-U~@3kKXqaxr3R(O~F_dl0kZ>MO|GX8F7A#fuQ$ElPP ztm|MI3-PRnwQRs;=ZtiK^nY$wX#&a%G2eJ2vOHy-R9*sqDo~Hv2w-~Oq{N6w07XE$ zzx1t!Wp478r0u(siEJ<|;4unxTF4AH1&%rQj7!DpF)Lw^I)Y3-RdQG6yd<7SPGs2v z%rp8I839KwFB^za@=buaDT7_nhz1!!V?LO& zz`@FdqZR@1B%c9l2xuEzrVM-P1O3>P0@8>f6*1hLF}2RDl6@t$EsqAqs?Fzoxg?Nf z1&^J~$w-Fj3eKcB)seLQ5VLk<1o>^a`xVWRRP4PqmBaHNy_(EpIx|F!z|1xboFYk%J zJz{CW7-5zvG1M%xtd~Tca8@6S>bj{Uj|a*~khgd&(VEP3+ex@3w?ls*bsl{PX-nxq zG?6Yv{hmlU+zHjP(3xl}2R7P@=mT5Z9hp@K2l7qb&|hjNKd-@U6f*J+?-J0Bc{s7n zD;HHCr9WGr+U){n2l{1FWW8wa zwxJR6se&9Wj4bHrN(A7F1KnBxo>b&!Q+>P0JkSop@`FzwzCGMNzsx{qlEvYnk9WP9 zm}D24_D`&~8LsD$%u{^K-~m2}k*>O%zHNTRF;FC|#>!1K3-Ev7-V+${hT*ZsPb(u~ z&vXx{H{Q@|6Jm3>RL0ytEue}QLAMzVd3pp<5I?4?1gaIM$^b);W-w(h6zqI#)Ye2r zP^W>Io#1B1&l!MfT7Xz1;oun}xk_bF8GcTTDin>v^)Wt2Ica7ll7b0RlYPP=WOz{&Czr@L38gla%WA`y^z*(x)ehR5-qmN3v0k*`vR z)ob|Z)0F8sn@vw`mog4TyD#_C2(pMPj!I zq!PG>XJR#aKsM4>op(pvWIB;yTvDSTGjG)`E`bONGB*Mzi~i51w5W3A!W~f+H@D{) zC2vwd{iT05eYUKqr@d4J($>(API>kPxX$Yk4$*>vdf}e|^n>(cz6mm4VBlPHx-W)C zl($(Or7NoS9-fch2E_*(s9{4KtAzu06q$Cs-Y8b(J?8}(LP9PKIdmAdVv)0{*TKpN z7=S=X9YrgZYKczjC}edib@}d5(QG5tLdDWzD{z0q52-o#LO<&Tqaz*JZqSt#%7^n% zr&Z2SG>UIuO=U>cgWR*>fdlcp@DnLC5Aq?m%LjkMPSSR79Z3STJXZ^&1v>}mLhY+n zEdNK-bPP?1M!a&?tzHUvcG8Cz(*M<5*+*3`55L#<-#*N|?|?(oI8_Fkg`Gg=`sl&= z_-KF0NOXrRhszqxAR)+q7Jqk)1085q5PK2yOtm+G1r%8wSTwpe!gW-i9j14ud5p3y z&72;bok~Oc^pi&t|6S&|P}|m#Oe>fn&!y+QCGp;_8VH_ryTeEH*`r(nxpO>^b#aiE z1b?_wvghT*A0}THHj&{s8nTZ8<(OdIaYU6Z<@1uy`-ZjvN8%XJTU_UXYSo9 z@CrFSXI*Uc%+$0GAk!z0IN&wd%|O3LLngypWSLnPSrL6fd~Xu0Gl9bN+ks&*eP4eO zXq5WVvl+}4ubYRzyWw{s|CcG_@Jb9C*lf}y6&w<~Q4ZTXjM6ZA1j{V8d@Sw7@@C>F zk{_pIaO6*(?kdvR3Q07)DmRpbULc*|T)up8`P^d5KHPrz<=vONm)n1K*z$lW>3RcB z6S5~nO$PWb9EF|-L!~MiDhOcb9Qn-kD z09Ob?3HX)0VRRt5N95I{yS~8Lu|Gmg0>|5SUn@c;fQzw%dvvb|-WuX0zyh(6 zaM6s>Xn-bsvfYrtc&Ka`WHmN8d$3T4%3>T8J{zvOp7+cEERd@;4pX0pbQUUfM;THS zpa>~Qf4F(Wax$U!W-oma7T}2VfFR4xcTT?%m_Z zso@Kl;X-4d4H2Ahj#KOr44XXd{gNVq6kwL;3AIQ7Ivq0uY|TbyK`_SzbPE6$omAQo zK4*jQ0GN#gTs?#%i8$@BTFFA2Ocb?c1q+~XWdz!aON?9)&+eP&mz=Z$gosLWjLa*w*pdoTy7!cghaH2*6Y_?J2JO)eE*SXg z)1@Ck;{l9w9ox4dQu*jNLDa{;m(ME=61xQ!rCC+Ya}`Zwo?EV!?N$&E9_}AMzRdmc zy&F4uH!AAXPrbec+ZKPOG5}}6b}wjJnCN27Ook$V#$_7rfy-}P&%0`c&uD3dBt2?n zbjGPeI)oBog0|34RM^47+LjsYZk@vNj>H)QX!i`(cR6rR?ehD4_waRw3G8oLUAWIK zICZ$&MmhLioaA&XMY{E%pgR$V8&82=+JZFmNf28H{trQ6B4~fljW~kgn@|6p9j2~ZV%r(h$ zvqG%vsG@bqv5sg3>BPWB^>@Jl$TNT&TIjWY{EPGo0UUiciyAL6T9v~|JD07#YRQ#nUJ zlJO`)iNpQopxTBuh)g(KK5?}l?}+w4-F2hhxM^>k^~Qf+dgH7&{iQdUhN{j)btb4Y z#rhJgFVXr^M_uU-s%mI}x^fhXS7QA%ZzS(Sm@rs&4lJR8v&aB<;0Pmi!le#8wV6kP zxQ*lSR4Zz3ODB52IPQ+P#;%*Vp^UPcJLSN*rcS*S3EjRf$JOYFp1k(c4T)!OOn)Hj{$4 zIrl0YAhx-5x;q%7XPp+Ds%NLW(M-nCOm>IMC#dUyW`JYV!$E=WPkyfe3Z!T}XTZnn z6aD&p`}p$n{K^|0F2mUtFY5}TY`RgQJHe*R+Z1M-Qm=Izw2En$38id3TxzHCri~@m zJI{Zf^V(AWQCYT_J6jT*>%-^~fN=|{ItT4*VUW_siy}ftVFXtGZc7Ffe=-fNLFumT zf%*MkmJ9~fgWWtgu8K$dD`g8KZCfCkmFnY4_5GFV*UEa--%aB<)EPb5&FDq9d=AO& z$`F**UUjP@;I5Rl5umOXGQ{rkkOnSpo-2Qo&qeOFvYm}^o{`99Mw8VU%{G6oNOEEE zWuZ~Vd9DJqFLJMy4Kn`hr(|22hL@Ohq0XPOf;yx7x>AFwTWj~1xHGjx0v0M(6gNJ`b zCZcW3GV6N5pq8!dhq}7NyVdQ`T`P<25LVam+R_Ybt2kUK8MM>F`sNHPdvkruuavZ^ z^K_4<=@y;xQS+zTzulER*)8{Ey|UF;iqdvFO&Tz5U79pK&z@mM>iUFq%VF-;CuCW& zvQc%?sL6&;)AJzDpH@V($DILvr~=t}feI zZn{>M=U(PjzEXWzzLD1}UnyC5vV;?y*-qhT^0U=mq?MNSS9-Bl7I91KY{q}P>5SIt zgqOwBd^Bsi>E&P}H_bGm<}@>0DH&*YS66E;i{fdu-etMU(e=)Pa)j3ZI_-X$^e<03 zKYeD1^V7le)8TQ~qgLT%iy6H(cxgE#aeeSsO6D~gZ`<-SUi1&V!G80R_lIBJf7n&= z+m7l#o<9CP_!!T47#=ZxD7t^>U|RT(-I2S@=mXHaz~~fOOd8ox3z%iS5`;c2kZ22Q z?$evJD`SjA3vfY%Wf-f_ha^(bBoq!$%P;7I;#RTVJ9>~i#*zIsjLuFP4w*ZdO`MrN z(R&l(78;2nG$vP}hnF6lQ(oA`|UzydFl37*P*<$Kui^a_r)9iWW3ATPjLu8wNHQgWal*4yG%8sn~XaJ6h=%jyJd5_^@cA?R%>^d(mioT z*Yq>GXa1bBv^uS$o0W01I%dz8_Wn;_-p?GG5xDH9pqL*1Y!`pRd%Y1x%O`NTrr|aJ z5{ifL9EtAUM6h8L5L&z_vno0oiYj?RfFnRJ;ygAAO=&#MtGNq~~@k9u8>-J8k)K~RXIpopJW8usns_5SO_ z-CXw$Yn6YATT`0E-K;mnN~8vwapEJ<+9r@|jowAv_;JHfv4RW}H*fR^UOa7k_EgN~ zH=FwIFSpP4w~w#CrpZ6lzIGTN2w1^>0h+LNwf^dMKYhJ>oC{OEEaX5=OQN~$2kolx z*`s9;p&c#VPoO;7xjgC%L<|&NjaN3z)K23Ci&}q#bNGUX?94GhtNAWT9uO8rdhJAF7$m zkJf)UIb#;ogkR$^>2lGr)0UZ80U903`TX$Yl92hehk z##v;FT`Z3sWAjDYGn^d}|FOAE>2$yxy^_O*VSr+cRD%@pJFa{UvutYi~ zEeM7M9TtSwf;cJ`Uw>W+?z|F)bug@gVGU@t(4M_N73)(zulO`fm$}Sj<)He+2x@;0 zP?=@BzBCq4Lx23W6&3VJcNP!8MEBe{y36q9YI|2!aS|H1Q}k}E0$^nEe*CcueMv5i zPvWv-QQ2DZ<@WiPnfr3skI_c49lac@3QcF+3A0W>E=2>Se{Hx{`MVFF?>;O(F}=)2 zU+DFLUiJ5Fnh@|6&e!xrX81VI$f$pecU~e|X)4l_Y`svdNqqa`QV^^E@<=e~s zhu^Dd<4dj10?)ZwU^$S2Cxs8^QgOu29OzRw$bE&p>#nwc4Spzdo)mA;V-O0w*7F}Q zv5P(T>jw{>=hYm_&D$KnoD2g4lw0>^Bd(4EU~W(2;b87>YN(-y_acD|zMy}lt1!j$ z)rLObeR=xJ-S078MUFGTR+9N3ta~LeiVkO)tZjMEo^2MR8!{C>n`H;sZOc@hESqUp zCj?4WnFWbwpI+(am-kP9o5BafU^Ta8J{DTwgq^4+7~{u}g$_hEJ&mOlz!(Mc2mk~D z@zCnduyzFWaUSppCNdKz(bs=m65}N1YBM#@?$%4Us*giB^DzTBKmm{Pq|u&a#Ve&K zT~903*5wPP{hsE9YvnoyBwSHQr!^(Ff~L(!F}=vLL@ZdHS>vWwhuz3j>b_5AVf z`Q7adG!si6o3Dou1i$LA6{}8SM3vk-8qK$7y>{tYZ5|M$(_Q)2`=@``*QYO2fE0(Y zo-Xfans){g;&+JxQ}G~MlVtpWA8iZlabyT7CiCrc!wCq^DDXO;U2lgqu)-NN)X9Q^ zr=bh>ET2PUwew+*fe>o_<@`KWoc8U3OrrY>oIMAR;NUoLuZ+Tnr-!GBVU6zuG1W1Y zG0+o9lJSzzGlUJM=T3jVQ3U96^RC-cxYy`BB?-;J=&nvOII0vI$#<0KFCVDIY57qA z#Aq{~9PIg(=6-&9zW=YM$Jg8WIyujlqe~im4TXT-b8RT zluo8?JWrF^z0A#J`Uv}uAiV8#gAvl608(MJe7N>{K?Gi1zW0BRFZUl8LXzpKn+%Gz zcv#7>5Fai!Tbf}pa^umNj@!7Gm%d&4yWX>D-+!Q&4|hMm&cYwylV}lff4EUZLM%Ew z+jXHUPn3p#^OBz zC?9%0xK2lUJoUm^s0w)wU*EOQ%>k)@PvjGViY&Y_{xLtNYh?*s)lUOJjRhQFU#GC* zv#0&B7nlWN6NMsNEP22}bGH%tD`3!e*)V5vLAZYg`gRdROYx}`+XjBAn<|{Ka1PEu zI21a$5$A-0Mj(yr!^`>j+br@{AUEG(#Sqi1w;)FX|MJlkng-qF2;=33Xj%+z;L}iE z>2Yn!>FK9?4(c#e){;B>26Odk6}~hKw7a{p`j||D?xkXnI8Le#X$AwUmR~JeL;y^J zaBzP*;9P}Zxrxw3EZfuIkyUsuXw^*P%0$o?Le)89_qTHb=gSFjb&2r)XlN8JTGB$LISd=cCZlp78ofz0`E%Q92JQpC$$Et9h+DMbz?B4#d_m`yrw=fS6#1y z=E8_n0|j%%ayfd6M|K`l%~WIROPowy9>RZ90U9a|I``h6rGH_ ztPmjFOM~RoMg|R-WskH1oCWIZ>yWL8Bm$t}0RcHC#a{ruBF{+Gav`wV8KpT7ONoCV zj-7plW*q&H&$w#_*_G5NN5nu_H_(CHWs7NYPDjF3DD4?dNxgOCd_x$I(*6uuR@1?t zPTFuDtf1pcc3jCS=(fVImNi37!)H5U2@UDwcIR{;47(Q!p?X1h9+|6DYGV*Sg%-<# zF2phiXao#KY$Rd(crcUFmQ8z!q*s5uSL~kD+awzL58eGcDU=l9#$v97of4e%YCygl zTS22PGe_xzpy4z)i?ybbD`)7t58n{Ya3YT6&=FFA0{}40XrNmR@}|>1w2gkS(1bm& zQ8qv;+abaNVa=3`t+q3c9Tb~@XM&BBv%myS;pG4e#1!4T@%(UU&XHjM)USU*pj(8n z84kj9i%c>~0)fdR4NIifjEbLiN%qm68wj9h5Gp2#(uM-bBH=lrt;a#+*{%ds9z&v>g7(j6`Cn=%^bJBjb#6ePbhc1vO^(th5x9}z zJ164=LY8U_wurPOKtHtXLbWFGc(RrbWrrxJig46R%VcrEbctkdzUzNQL~4?m2VTKZ z<1SfU~1PhoQH*}98S+GZf(_x8~ZhpU? zZT~(#Jl%erhaaah)fkq6dC9+}C%^v`efv6ZILc2!xXU!uCgK0jphe(eJZ~-gx_w-& z$7(F-8~}Epg--09K*u=*k>*#7Tz(m?avm)z(^i`Q>GSL3-OGQ=JNL)1U~hcU&qFgc z${SV!8%7TF#I}Qt#tz6Pw9I7CP5KD#~*Z?pva0?^`EuDwC#b^zTZ-Z((tkvMd`4*Y>6e;^JG^BJs*uL&T% zqxByvVm{$s^o2JDs9y}wsF`We>L2RVdLw@KZobj0wCI1;>Ay+K^Q`5UAll~jd-*As z`O)vRcwT<5DgBqP)7x*aPct;6KnS6*O*-SZ5zd~VV>81@(L#hERfHF6<^Opd0a;QM z-W19LhDyVAG|FD~^=Yc@R!~|GcTa|u17i~pLM}&SmE90bi5_sGg#!U#$Bs7!xIRmMSPOlS-rqr%3+<$DswfvAG)LO8jU$)sx7;GAqo^LgN(}T|i<~MY0bcSq{awm(OcD??lEf0B;t0?W&Lf3~b9(hE_WW49iKY zEtir0peoW?ZQh^N=KbbUJ-LgsDF+dv^KKAviRXW z&QXhwe*1Y2^5uoHNokbN3f6;bKh({@|AKobcZ$eUgmRW`aAN3nCreJ1KG<^WfJS-w*vZOka-Kvr8MEX6$FFAF-Cp>KsyZH8;fdT;o6sQ)4RBVFt5fP zp#guBqQ-%{-*A&85+~|WfqS*ZBZ{;K9U^!8bNDTV4H<^zC_`M=E3B*;_reaGMz-17 z3zOiiCIe_RY?1*v2NP*}h!f?k?HJCE!XXKUb_zzYQ2_`eghmgd0EXq60=WPwq&Gym zjg~&55$t-4T1MeypDfA0txcIjn?!R^K$U+O%1d^+pqw=LFq~!-U<$<&1(gznMT&x> zFmU}K+*16+Vr@XNXkP~EqhPP)tfj!&v=qTj-}&`9T@0N|3jST(||B-4}C)+Kv^STTc@I%A-_YSW)cBcidODu)Jaey_mLNPe34srS!D}vItTx>-!34VXa7}3rtdWK@Rr!;K3V1eu{ zP{PLc=#WmqibM*=DLS*&;0PEn#JGP39(6IK`CNttp>#F5WM#zoOd*6D!hKQ^F)RpY z2T#rhB;yz>5L z4AyuKm+l!oJPlrINGy-pPjlyOe`cZOh0ULXgro6_SfG@>MY}SSByzo)lzD%X92lP_ zk|5~oO*klQQO{+_U`mQzNJs{%xyWAJ@Wkq(J*DMnFPlyxQd*@zFV}^YA)x2C^Z5>E zOrL_lP~9E_fe;j&?7+j0G1?O2=K4Ju-_%Hz9Z#VEVXMNaQ?_)s zwKQ=3_V94`djI(D{nIS8m13#4(LN|#`Cc;HbM}!gXRI~v84iVbu{1uIMG4DOM*|2b z+BlALVAh`}UJWpDCY{$ErR|93e2@iq$n{oez!HJ&;$^6eP@ijk{QQ6P{5TJ1i#R6J zplI$A19Nc5WTF!jYq5wOS0QzVJX|EsCS_(iC`dwaE^dSi49YP|CFl>v9nVd2IqO-0 zv)Xx=sHI>Ol0+R(yPgsP{u0Q24zoTP%1Okuu`@h;R13q;!!MT{yT2*c1qNwguSmy6 zhWCvM?9-c1D8;F5bg+MIZ^mtCqnXB_+-?cVO`i`EMT9=~xboo)BuHbyA5;0(M<|Zu zYzj)7`estVlvlXH4cYB15*0%QP)#ETYen~w&I|`myW;gB7;y?P1Pa4d4}`W-Uhe*W z_lD5wH(@sX07k^y2ouK%i`h*XP{YC>|1OK?Y03w?8KdiFjIe*3^2zSP2X|8o1?Q(m z2rf=-6c*2y^73!bFR$;uJk9JpZ)m05Hunj*WAuEWtr|>7+M(1%Klv$=6tqqgST$Tt71DD*!|R8> zs!VZ)7zUceN+n^!5BbhM&IBCyh{$7cxE0_40ev9e<)s9Hc01MQ^Yh{M!{@t?GxOm> zlO}qY&15vYvq)3nYcj*i@%%n009S#DL$S~`J;T@_d}4n$+ruUl-urM|5fwoQni%#j zQ$5Mk70lg1k-!i}jltDu`NWb4M!Q)FytH>zrjk=%^nDtRmqZhtZy~SAl*}^z6eFtd z80JqP}V3 z!d=z+dh&l^PbhyV1~WTv{GIGzMBy2kenSouE<}iV=<>aI zR0P*I%^mRG*2=nlzjzYXiuY?ZiyT*E^J(R1_kXTT;Jb(0zu!Gim#~LwtPRvo5t9mO zes^PV9g5QIjU+79Om8IEMA&Bd>A@IiU(9fz6RCgOii$Ss_mD;uk~zV?K(jyWUd)w; zwJF9rPmlUu;jEHEIs$BDi0K^|;kb43z)({By|eIDDAd_&-PHcgFFhnUC~F?_+E=DG z09U~9xIndlbB8r4T$<#qNgbO+A(%BOSd)S^DNdV|jtt`B=&#vRyHSZD57tm^=m(P- zg@S*C#ZZ+(MULo#tN z!xBMJqk;6gNh_G3h+$_W7b7_Op&`~m0&fq7zio@9ksvN`sRU@8I0OkyebI$w9q4I? zsQXSA6N1785_>ghB>a|Mf5|CxXEL1Li`tK)~nMsS8nt<}^>5W4udu6l>#QN8fSmy z?6(CV*DK1&%;{GKG%fGOx*V?tT#F(^ecpbFVmG=E3%^M$N z6_L@zV!C#}9-IPec7qcxLVz3?mzaMsEDtoT1BvX15+qlK_pgrp2Snsrv8^YRiJX{= zL2`OJ+{v645(gbegV|J(>3gFR^Nx0D48^$-RA|QEG`1^meBq8yZmI?CRNO&Y_~lbM zVw5zHUT`v7imow>!@O&h;rP{v%QpOh7Fn2)uz{%iW`YrIq-cM6+BnbX z_K2KKxjb}6G~ja#80FvqDJf$A69_L+UuX1xr>n-99cdCMg*Utlmy}q%IS8M3mI$;B zl`L0+VEg9P*<6DylA{28m+8WQ-xI+E*JqxN7W@--J&BAewnE5Ur+#uaYR$Lf&bEO^ z%A2PSD3Y*8w8Nrd#1Og-uRedd+Z~M{l6QMO{XoZ-JMv%9Ju~msz6=yC()Gat)^O7Z zJ=YO8LPc;zVoTaKzSQxf!*z9V7RU(b7p(xzm!&P6tGl93uSl%zU$yPdZb&%t%~X#E zKMe*8v)!p)?Zp58?e69E{^@awQR05b^K^bxAA7m^>p(wB%18(5JThg@FG84mD<;@4$kY{-(Kh1w}^>ORKERFiAG#6 z__T2#*W3K`@%Df3Go$lvF9}2br?z>ei4X6-+|K=^;UTH8by4B>4h-q%soyG$&qg!; zezm&0=TCDu9I)Pu>SvMvhNyU${W{2SC5{RD9I|0=Yi|aN3s)@0w1=o}_3QU9FLOaB zQEn)8iRVy!0`=L`@wPuXeT5QE#Ey3CG7t!}rm6 zX%Rc|!|j(3^aY*+E_J{O9E+>dP1?r^*iW9K|6t+lry+PUm6pNa2D5+y4_5tuUTey` zx#wh|#EE~G4$;}tNygai8a}`v3DXhxV_B7#R%BwD-Yrej3vuzlCYWh@Bu3nuEt|(J zNjK1X=WtLQKhJ|H9XZzAWM$aLk?{dy?rRP1DZnX1OdYUegLgmsXe7-Sh3Z`4J;|AU-QA zjtd3;WMZVi?`8`8$@oEc86_DW0;tnw&yRlcxEcRmKF@SJn8k7S(-7s8IL~$QxUP5q z9hHBL|LydQ*7&=}&$o{sX15kpQ-l$l?*05@ZYg=X_Ms#Zsv2&3YL$nXA+&E8{iHs5 z^mF;xNn^}@`+kV^0)l$Tk(Zzu_2wa?utaBsnD5s|LaS~?&nR6m8^wtcl96jzJiIiEvZm?oAy|^P>IOT|~t%{Tk7syV*fw_Oq zEZXsD3BqlobpL!mm23q1F2eSy5J@--QkUsU6I)N88pAn`K%kX>^1*0ZR1|7Xsk0KTdLxInBYDm8ELC{+3nhs*=5Zp8jV6#40idgT-kEVmcXTWXTSp*HfOjnuHxIgBpq8X#Je(`71oub?#e#=7C@OzTHUd!g z%Beq~A`kG50VsZ8$RUS~fu5u3m8bf+8=rJ7?|qN8P0W;Zng$({dNTPZt}PT2ygRdv zSfgZCF^Pl0JpkByn8q}FFx)r4I*HoaBawHQ*nLNwubN6<;%Z0zY})>@vMJCQv9#UR1$Z& ztY!^X02{I8+fk$AVD&PvKYKB65W_nyc!4PGf*qDgEgrUS%~~MO zvp7`Axjy)V_XhX~FKhKuBP3_UDRs|X>rWT-ZIu1mOB`#U+rGUdebedrTgK{J2 z`gWbL#v!z8jMZ8H4^DrGuRlM%z5ikDuLEJeY>Mzh$p3yC$a*hpV!7{)_QU@_Y=Cc1 zKen5A4loHpzmiA*(TJr2LXHMGY+wKH72<(s@r%{5_X^S9|n*#x{ z!roL7?F#%q8iXM#rZr?s%72P0P6i&v8%}d>&%0Gu?DW+DyIgC(u z$!RTyXww5-4%)bcY6!XoD~!ao1Rkj;Q;PNqNDktxS|0KgQ)&*m{i~AcR=HMl3XsSJ z29h|;q1`I>cN>300Cs50&^8&=7aKVgR=9j87)uxHlIE26Or%9TAT7*br9UiEoC1 z>#k?q8`co$gn>j^oB(`{Yp;TLSPvzwVaeK)A-4d8cZGj-|Ba=#MW00G zEL&U&iGu8zXT`{XAc(dX@C8kIp#A6`(1Ym+B?}r{Pr7S|^eD*dv{E}+^qAY7J6={q z%2ZeN?uY47p<-W_T0;pOI)0E|)5Y?QKUUxE4Q z&a^Q4V$9^w6 z@1H+?dVK%Zn%R2>X4CRbPCis2K)=x%%CIIA9QJ=CtoIs~Frl}u9n?_Pk1xMRAp6FZ zgEf?a2Cr%D6&6D$M!mQk2(@Iw66ToNOM6@y7Y76(#tH@g^pP#BsD+hjh?iD5`uh$tGItY@kv9S|Yy%6hw(;47P z+%tdmdIpJyUSVQ<`hZEBlP(8WZjq-^kaHSm_84s^($m--sBJ`#c84Hg0g3uxycr6T zL~gvHt4n*>3mgBGFC=?r@cTg1 zS~6ZvPkd0vj1x`6NDfbXhDN6QcnW`t^Namx1};cKV}Fzp%s7|-ER;CaLl?VDM)Ts~ zM*zoUKH#n)c6fkn%(#&VjQ&v!-xm&HB2_Z+^Y< zT*PA2N3-0cTqJ*qirGN)iei6wd$bk1cxNfiBb~HuE5yT;zfXqnc2OFhVXIV9Yis6VH*+MU0|BUYed z`~-N)8;SGSb4&rfwf29t3EY2;VqIoi8VE(3di3;ZJ-)5K2Et0+K4ajpBo1=(n?N2d ze;LAsT`mcQN)ArML z%%*v8*HOxc)8kjZ_R1l$|DkWF3$Aebn?N?}!l?49 z0xQMVYlp5~ymo)lBib%nhLc}(vCD_X?OYLy-cT#-bgjj)=}xu6t&XPg*Db!;^+T?{ zF*M)!?b+?~9G{W3dE_1v`h?b87cF=mR~C&uz{PR#=T*I}s*SZ)E6wVRRW^5Dt1#79 zqI4k_VQFdzB;u8EH|>7NO<0BnNQk($!YYXAP9}}=PqlxhRWs>++X&vCpPus7zIJ06 zZ95hE_Z=4`4&)#B7K0&C!Hrh?k2^AstOzfVF<1dAXYJ9()uY?aBmF-*k6_cmxanHP z=^I~*yZwl-kMCX|KfOM^J^l3f?&0Ix3SR5tNY9UgS^GPKyeR$!)cA8;H<>obqsYY$ z*%!FTrnY}|Pr|*<*xQiE6mKEc!?tV(izpJPtvjZXar5+4bR<}S`Eo!=j(DC(Kn@>& z2ad=H5vlHyftrKQar7F8ol!M=e~bPHG|+jbCeG7~^3-6l)CMM;)WiU0uTd3%-LcE$ zqp<`{Im@J5FdC|~8xY!Bu>jbt#@zG`P=`|=D@}j6FSF7N3A7KlV=WP^?QmO;c`xtp zT-P;?1bRdCK6xM(>9o#bp@Qo!w@5Up_VlYBnOBZ=*s$BKUrcb9!B+;Y8>$F|dEs1V zWI?qt%9GD1@sZ&QjK~+mpWULK9(W+z6`4lFUP3!7^-^`w%Vr1R?0Io>lz|qP&E}%s zpa_2%l`2@CeJz!#OSM5Kx-GdnX_WW=jn*NbD{evuO z>nOra|3EbGw8_Od6$o$`h~L5Y z&sq6u`<44P))1|ZK#G}fp{%jT!|KMa>Yl~ppg6J1UIft^?o4;pU#7<`_P$dFG!Ytg9Pg^mBfDw z#nF}(Y*C@!!a@a7gV+xJ$&2C-o8M?LrU}>`BOoa!BiIDz zUmz?pYZu>(yahXgR753ppgpM4M`44-c(V#3<|R%Xf_xq}O5PsmDFUYBZXka`k*@~~ zAz7}xfSk;%L3ve%PUXVla0ph`Ss{ru2}VB}Nnbl;)fX*=z5N-9dX5T{MH{DKiQK@2 zfC^yQhZP;5v=Zju1Mvm(&$2lyCXx-K;EKMnv5Cd)d8tH3QkjDenR0K2f=yFvILOy( zf(6FNvvECH5a^LCz{}}KcVvIAAs99t^ngLcP8^&WxSZzWGHG**+N=gGCiDn&_WJ#u zG4#k+5-q##S_pTaRW!!GZ7s8pA3uKn;d#6DA1G&RYrJ`9jHRG#OdtnncZy*HwS?*= zd+*g&$NqgY6Ym~AeRz3(YJ(O9Rv=$G690@Ia_?~k($kJ@T9VrW9oztYvty&Tkihqz!1sT0rw_c@#!XA}6YH;UgCT?1 z2xurnz$T*U%bmdPp1ckud?k?;UlJHgZ+mT#L3o1XL7I&XIhqF2m~f|EU%U+9S{1M! zEAs7l^uxo`%e&Y2KRiFLWt7QQppepVcjd&9Po><8dyaAmC()I7aGXyI#GWn5AA=0% zflLx(;&Oi*uy>kZ?z7RGPwTm<(H8g(3qTl!90Vf}yFl1twLD;7m4bj!5i%`O>H{^~ zy?EX89X|$)RcG2G<4NXtI%r|`_F~KiIp$6!yu7`8cxfl(#1;1-->}@-4B)v}zyc%D zifCU5D;g-1O^+gvS6K&XMmQ;u>WNgipH@^CN>hJg3+R)HE|^+~1p{Tn7Z+~mXfD8=oPd7FxxFj4W^wKjnp&l`H`TM*bnRDoGI&U}p!;KnU_; zp*X$Y7e%zXGDoy>CV}J#0TPI8P_WqnL5mC%KV_qAbddQFBA`ff#U?F=ig6WSVS0$` z&?xAZRebdJWFhQ)Bq}(X>7QCM!AB1hFC&u@py(|1= zln#S|cwq2!C$-YZ(Q-hGjYMi@iEf|dR!4=wfk~FGsYdgO0<_%hK#X91_kNbYYeC#i zrf41SuGaA+1y3_j6Z?1Lp;OX^+XOa=S)WF?wr11~pniZmA_ZrM3Jpv`cMF&IK734e3QuJ<6 zdE8~=eWENk!)Ma!7M2t@F_ENOLT~_LK%KvYZi)L<`~AbGx3{&)9D4~(4kl}ut~QWp zpRmw>qz)?CBl+Lp;^5M@la#B>B(|{jzAlk(j9x!Hy}mtv|MKwTT2R&ktF-PWOPlLW zRdyPG_8+$CFiBeO)&=6V3-pUF5a%u+ij1BP?LqCbHsM_RRXNqC?&sn2(}o0)^0Z+| zbnos&Fy*v0WGJm8Z#TU5bmB$|)g%U;_KbCZbY#Hd$R(kS-hfLz$;c(WO@4r)h9bBN zM;>m%@2TD>;U5Wa;BjY+sY_aYveQ8X1+$tI71J1G9U${DXAa!8Ujwi289ng%br-J&HAY` zHq+=%jEWSyDO%>qiKXr=CeNOSD2=6mw`B!CCNl`a>#Vb|lTsoK=1y^=4t9H$0YWUH zGfDu2?3G)&egE|G{^R2xBcUpKIbkp@^t>O;VkccB6moDzxRg|0yXkA$-369>!)$Na z@7J-4>xjwre4I;eWm=SSF8Q)HtbV>ya!?`dQ44=-4&krA{MVbyKOtW7n_hi?>(l>= zs>!cuqWtTMv6ugE{~6D8qKIDTxMLQpdHV6;uCH>}A|Hu6NZ+Hx`nbY^TA0C_kz zfI;S8*aVf?y*Bte^Zdtu>n5vv-~1m?<{8D98UX~VIv;*4P&+1;+nVQF9 z^1{+@IhO$+Wfk>yrb_C96$6u3hg_8Fc4dD00ZM3 zI|ii;5bz={5lWK+w*mErU`wx<4Q(>Ly35Fw4@51xU{Z+kufqE=>L__~rMt%+YByr1 z*TX+cc~ln;b8&uOrS3N7f4*|1ECN|KK|Yey8=)Ra}L!=+)^GI{_Le95GeEh zw|}i0W3dQ{oq#%j+FrbWov#01<&|)@2={(AT2|wm2s;IFU{BfA4U4 zdyS^?(%hK;%;3|Ex{eamnQgd!p2a8g^o;St4B`SfUGMmZN7u)fjVdinrL$EOJgpZ~ z{uwII2E0pqyYwHQ-amYN_w(b!=T`f{A(JJH^ae4IAAL1U|MxAZ+qaN#1j3Oz#>j@m z6A<_?hI4XDkV@5mT<|8#&>swGUx7ddx(|L9eE^-xp->Qhq(-AFJuyg-{pJrqC_CX6HE*KL+Pvy2+<4d$PO;D60EMKy_YI5T7cM;BTup6mwD5pb6%J<1H?z7tT-?Z1ikm!B+bCBIO;ozNlcuG zj=Nmv(O$`# z6?Y=F=rAr?fJnBMY{J3PDDEqjq^=D00jEWF&LS|RvI4R?){GbPNjPHb5z#{}C3H;{ zE(1xGtX7Iu)#>`UonHUb%k!sqAD+K__YokYpH~`x(ASkwF^c?fntHO#z&hdUTr^*7 z_bE!qmFn&vP9!vz1=-bm)Ae2+{FN+zeEe$*Xr*QVS^1|bNaC|6`FE*$0?CvFXste7 zZ#a|q-tNVIdbZz|lTPW@T<@GO|CKzxJbnK|lS#@I@IA~TpT-#fOdz25LEIsEdub)llH#ccfg%;M*ozf7t62dKu=^#;4w+r7L- zqy?_t>h0Eiz0-d+hix0=9fhkNZ#IreP--44$7azxDi01M2ISW`DL%-CtWq zoNB(@nYXE&7T4c;#pe5$`mIX!Fk$$fzilUf-@Nl8(>z@-zx9T_@7LE))R9n9m2bKe z97X~CP6jBk>$lH;`rNW~Qt^f^D#FO1djAj%ikeO!-1u29G^m_t}KYV#vF>xZI)`bgc#w2@tABo6+ zC+QUf2Jhw6jx9z~k!!7PH}O~z8VOJ^Ae>a>y9kUKE+i`RXUvg|5a5uFitfppnxxTi z5$UnQ^muAhjHlQ4&(rejyT|`oc?ZHGf`YUX%ZLg%eiy&P=Jd1(gvYc1i$vimO!!(w zxKP*dT{1-}Vd@L^U?m@nFLK~Y%>hAwfWx8&tWVvR4k1&kg)b_cnn|>8S5tJ zAD=#N*3-jXTtzmvtK7H=!b-bRZi^!fnMqCbV>}M}(hKaRyK5q%d=mo?73%hXY`9sR zcMtF1KYv-t022)iAmx1$jl9-q(H1QXTZs0%*m;I%B*|8^(VyL_jzSy#xjLQOvbwf3 zt}Ux;Yr@*JgpeY2&bXup3A)f$%m5Z-885$2I!7wEa9nooZzq#JcI$OA89{*l+QPEr`b2uR zi#YSoMb8-Yh^{`On>hyRBZlh}hWY?R!Tp7TN#ROo19W4r5TebgUiKG%vqBSbe>)YL zYjyISlst`#(|V`hoXFRI7qV*8wPuqQ41dSOVo!sC0v!>%24o}F?5BY`84|%2>>HTo zES_*(pT*=CqK;919JGLlRe%$PDr_|821GGNf+b-ToW|nBOimwYT05go7_=FhwuG{6 zkK?APMtTarCc1RsAnBqWE+VQ-Nf?SRBO9Xv4wyG0`jufdC6+>eL8Cev#3dWD!RE89 zNMcI|cGkn(mrTgEHw6BoFr$G_1c|;2vMhTeT!W~btMy~|oDv+VFAiqP-)`#tFX9DFR z#WrgkgH=m^;!Q-6tGR)DwCAL6b}~<87*LE3Y~l>T_K|i9aJ=kR;$PQ%C4CDM4Xb9+ zx2+~`PDecA>cW;>$Kog1>lVLdiE7T1`KBD}${`ne&_wM+dvMMQqB4EfcqwN}Coa}& zOZ5*rsi(y-ypKtgw{US(`OhFexT9CZLUWgI$nIf(Dgp;?F9Ul=KD=B&WhK-sw8xL3gqaNTwA&*ML!8bNS@FoY?Ar<4mQ)jSzX$`(SM%2`zT_ z-&$SO>g(IXX2SYkH~>eAo`L<&ga)Ftlj$x=mBDXYgRg7AZ<6zo-p^Czbr+HwBaTi> z$;zLk^|}8{ zPVJ(Rr|0qBt;T(SKf4U4?21A%OW`~bvL#< z9fuWnR`nF_vKL?ahFTF$i2XWze*gCHeT#;J(c&(gWJJMSoI#vRL4~7!39OZW!-ZxR zCZ{3AI@H`8<{npj$D+Gf2b#N7Z4$ND%~xEzB~E><2zx#2SBo;5z!ilNtyG8o;z4PV z@+O?Xre7DO<2{Gc=>Vm;?uW~i#MOkYf>$F`$JQ?jgF^)8op>GAHAB-c1l#jOzL@N8 zS@sSb)H8W4Uvx`w1(o#S-TQ}s&u>pF*kdvB3TjWVY~miZV?k^M%XUXcbbBZmCuh@) zhhwwJA&7;GI|o(|y)M_c4fZm(dKtN_R#J+qSHZsCzPr*a#u}Ow4?(n?Va?>pZn&8& z$>iyb$+IJqCmy%ceZI7t{K3$j9ify7N?Sc~m#KMP%fSS-i1_%1+yEPj$s0d^Po z6KJU)C^#$iyuSz`)QZoM>4_Sx*S6wUoZx)#zhmXCS<^Bx-<{2bzh0MTI3_6e06wCT z+C-38R2g#KF9dnc3^MLdl0Ip7qTK?`kI$`j3vV zgfN(Ck+y8>HV$8ZGHk}6qDjahw5CAIcs22?Q>~zji%zB&c4_6171Js z{GIK)YvWw2-@XV5gDpe+92e7!4o9-_iaB%u<($-Ov$2O_!{^KI#U$zD_t!t~UVr)Y ze$^J^ICsiLKb>23ts1rVYZoA6d{Z}o*|t>@M~#A3CuOdaQtPCj>qKM1SxUJHZs<;$ z0g$k!s0X~jqDoG%o+cyxC1EsK&!~-2?n|oJdQ_9okRJr^y=s+(-IHF)Gn%q>FI?Pl$PNOrD*2d?zf3A zpErw(NL+F@TCFUkw&^?kd(4l|A0B~rd-$b|MC%)HQP@C~`dx^UHYT1T#nZ}BI3+M6 zrOLo7Vk8HKq-1QIj#3_u0zUB~uy}vk&F6P75APovKF_i+RiIL)L2!{Pl1&l99$NwU zm2t5c_wqDkl%-SyM?&B7@OBb`3CMh7CMnI!OYr*2_hquRecZ+B0O>TVE|q?~NBwh<9~VP~RH`zzs0=?YzSZu{tHU)Ls#s z+x zu)p4p>nBtPDC;vIMsiN}*Q4Pe#oED?YX?(l)n8Jc>qZGCbt7DE12tR+lNps8f0IOX z7M73n6orcjKC48M=I{dY=deUdQc)JI`aY+>!2EEB|K`017%wnwjMRWfl26PS-FYh+ z)f1nc@xY{`cwiC{JW|y3O~`#>nG>FxSZ~y!N_;^|Odj@<7#;q2??`fQ^-9BZ8X+4xkG`B?Mzi zcL(x)u(pE0Xc^DtAv~6oX$EgH%>x;?Dpd|Ng7PDUduLyc2zGu>NRsOt*A$ewoKtI< zQfeUqYeTjgQvI+g)fAQ}T~?!`fD>C{O(9bq8tnDYG(nBzsbB-IseVpPf48V}1a_66 zjuX_6g1S{uFXNwqzr5FV)K+EAVgp8!N2R`| zmW~vvC-A8O1(&iy$m%ClN>evt^01d2PU?Idf<}sKaVR`kNV!F+TMRjW-iLaLh-Pr- zN!?wNW7l*!tkc=DrJ+Q*)d-_PaNJSRG#a_8n4N>wgT^jZk47|Bf11WQRi%bM)vzae z*V!ujzS!r`;Hi(KF;(C0n)WsV>q~23Rs+y@t#+YdT+QX0*7FBzT$~EjCg#I;D+M5kVKP4|m5EY;QzEn$B#Svl*tmgsAu-c(Gj zl#`JX@q&RtbFcR{e-{t-cV`***S|il+13$*0OJ?9((Z~8S1>ApjQwHZoG1hz#l;cw z)Q}ZyrFv5?^l61zyEIVpW~jfLEs{sZq+djIt(D>>wmG>&0xF zCrQr*!VpC*TZM*c6?T<+7=dyCS`m~xkYSf+tCS=i7H;W+e|G|rT#sP6blC+&JwJW= za}$L3M9rrdScMz>*>t8xQ3$ zdJmkTx9E!Je~%v@zF(;(hh2i?Q5$bev)YKugyJqVoKgP6yA}KPl{%b4)ik-7$&Vy!9~)!I2JR8ze>5F#ms!|9St zRV&q*1b7u1C;o`%HFQT~P)IF*Pg&9XG+varKAnE0()PUTf2zt8x#d7`n%1s~E*i{$ zP`y<3(keUF`kO1%>UXa0`2!@?a9h2utv|P_Uf0&X`+D`RqbUDWl?tEoB~|fpjWLn< z7pM8=f2+m%4`?&tPP3z?z3$3Nf|b;xIjtG`;# z|AfIoidL>7U3&%u$RK6%FCFDydQmouez4yOLa>UN33+dXc7zt5?8#J{8@v6qvdbfb z_z`?LeWhvf(Jy7_xv0vQMjx6JJ+%i>RIEf;HBVVO*gJ^>yIBJ-&+i{!Ust}TKUMiLw_k)E6unNc1I`@KgMO2KXZZDk{s(+;(g!;52V&po ze_HB696*&!6+--Wb(3; z69GpfH>ok2MPgrRaefAe@W z5M#od3*)C9`T9u!f>(z`1mpB-AW1uOrO@t(Eqb&hOKm9TC|EdTjgFk7C2MHoBG%EOALn?;8X;LjCTj@g zBBnCW=Wk9WYl5^tQ}y-I(HVSi@ds=Uv^O}*V6s_HxfXaNQ9g&`J8MP zF@EEnk^{Z7jn9u3SuU*zfB9X~cq~+}Z3=$*7V_X!wXR&&9Bf3Uq%J6pPp{7(H;O6)rApv^k;kR& zm@A+aRwZuT!`a}iz2BoXM@X4;wkey5#<5(L05ULp2yrDf0~QdNvPWv(5^BS3UdJGV zz>p?!_W6pbIrfTj=fif2fBE+Ce%il2JbheA?UqYEDcBR_VMam^DXS^Fi%!?Ad!bxZ z&8jf2fq;0*dForsNV%!YwLzD@3CV0vl7k70!>O*oW6&R{qC3z?dJjDd{iGZ>|Ibw6 zA{Y8J*7==!pn>E0^P1M%V{?>^)En5bCFDI{78`V;1IHv(hQ$cr#-0QAWf z5`)v*Sh3Q+e))b*acrqsz@y(s)^4@AAAHID4`1Jna?QsPS zM)PXNqQ0^4L|Ax|bl;7Up3O>fBXIAkJ6tN-`I4J&({F&Me@*WY@H8At6JH`hg`%~= ztrAU>*xP!2;k#o$Em%aX3weUUCX^*BL1;O0V{3(5oh5+YFBx>ZnL(G6L?;H_jtsip z%%JO6bUg5*wW|`p9TTR-Ry!v6TZMmp_~~)wXsz0-?C3*FLZ80EQO~crI#0vNYH{^D z;N7J52w%(le_CrDON~pI8IdtGFJm-;yIB54VAArp+n#5;BoSJ_XC1BND8qq1U$eD_ zh8%@Lv{QpMp2CbZWD~N)cK_94zCOOaJ$?Fq?G!Il+a!`fU#l$h-YC~bN zcj<`Xs>o*rI}?JYrbO7YV=B8FCNZ(haKoSmDN?Kxr|DiYjif2TRa1Mv?`1#Z){vpZ zN174-e+3fTwFvv1S)i@W{PvkJE`0t(@Y*z4B*rqpI1(a*DJZ9i73yGrcjVR+nHv*r zb%l6(#7&E;#Q{dopWl3gL^gQh^zl)4zU1@Yo*r+C$8@bYOt;dGF;oc=S_ljVE=P7%uo@GQ2G!3B2)bjqmcfie;yCaVS#jgB4(#GaT7LyhP66~3y0OQ za^t#m7SH(R@}0N`ak{Jy_BXHW&RQzEb)LiBUK9p@#+^`$Th}^cU0LVImECv_V`ve3 zdwZ%^JcrxACver1cH=|xPTnw=ZY%o6r918N^Di4sENYaK@ti7wvXg?quDcf{08E)3 zfAtED_8s^nGTg%;sw;`W55$~S;GkJ(U2n3bQ&Q?h2KFaKr?7=A??4iAFB+;q3vhv5 zw+i(QWX1@JG|0s`$OmFq1LzQF_{9}58IyscIHoL@IZ0C7K#MF39cZ#8N)OT8cpurn znRQPxOfPJ>i$bYWjz{bgG!H8$Snn2Df3RWchFzLw>r7&OCn2ZgSV4BM6MH;N(y%(; zQ5bR%65kbB^by%!MA1+Xshyue@BZ|G8smxe|Lt0 z3JR_sr|%bO+KiHTuE`9aDODK^I-5xlV7j3AJbiD#UlFy7K3hGF)^>$N;S*8T7X~BQ z^^4mS2$8wi1=WtGa{*#0+O2r{rmJb|99)dT<~OVrSo3*K`~k zOC9)l0Ra|~5(t_5Jg0X^9GLQ!^XTx6C(%EOOL9BteVLZPFRe!~ZYoX^t|&g~^Cl4ids7hefeyf0q749b0?@ zu0%aQho>sHI3b{6%%BQ<$dj~I(IPEDxrg5TP?E-a9`4zDe-$xX(?d^(19L2t{=lhZV4p8l4JA-l1?o>HL>kS&ydW0z?kw_@bj(zSh4s2OzLcD>B1P;ogSVnP;@aIcFn$Y95 zy^KP@>!ZAO*c`omZ8>W!+&n+--V=78A8ub;=qzz70z|)JQ4A}XfB5ROJ8P%Cf`qT| z;46Wm&3Q*Y$ud&j0jlVXJ-KqrBB~6(lAVUTWvl|^)>u7^ZldHFbqrGg&AWkSUPPtJ z;W5ptJ?+{E1CeZcO-4H(w6;S3mv?)5hF6qW--9{^iv+}8%ddYhXEG$-88O&pWvq}i zh=+!B%2*+Q&J4lef8aFe2o*<7B3^XBW)7qym>g`Y+e71KK;-NIKmj>!A{CVbhBA^3 zVfiICGMoK4O($pPBLJ(qi?}pC3P-b^k3nnTn=xjA*Yr*Ulv57T*&VZu-5^8t6dK?6 zb%f+WjiouW9^9Z3k|rmswkV!$HR$ij(;K*zQa1#5I(Ja`e*k1av(Mt>l2AG`0;r>Y zLJh>%H&%``^CyKN)oiMLNTN|21~JtqZGNXwgQTg$(%^ik`(n+Dj^ElVv>T@xdOd1| zq_vRa0?8W>qZTVnP~)8o2eoZ2IeHH9N#mWti1~kG?e%x14bAb$AJ&7R-dWg!`M|*z zKc1rqYAQ;xfAW0&%4}bop$#M{Ym!%($3U(ZsbmDJZg0O6BZ#NvF5+`A%iuRGY4#h} zLzayp%L8UcbwI5LPXnpsUHy3#XvVb?MYR|4f7+7=JHi*xv>ohaI)eGQW`|d9OZegG z?cMv8gejw;=-lbFRyY#7tY7g65j@e=@JZMr4Amx43&-DDBmH&C`qp z-T2d{DeE%LUwwrb!6OLNX*vV!{3x zOb>dxVH&!v{+ta_sy|~Sb~B~%o*W|Ix)YeRf5`aj`<878m7Feq<<|wln7>5$P00)y z;ecZKV%tglnd`Bx^?P8#Ka%nZRzRhl#@zdpT{QysUYJM?5vrn3&dYK7b<-jefi@V#ls7X$I`_R)8*fB&*Z zoALfc+W>yV)ljgS=uNABHK1^Q>TG}=MEPF!Ci>^s*B>69UYe0VnAjGP=Jn&9 z;y+Vhyu+Cb0foEusPq~u8nu!e|}y0WXg&K-7kM*##sC=o73fgbEUSD;>2KJ zNnVW4$lvuwxQ=Drx}HICdExc3yO1ewLg!KvV$1Z8?V|3cnr zY6-COc`=1x3x438kgz-1^X?rH?RX8?A?(#glB{eUEUP@P5`e`@1xrTQW8!Osv*4Bd z3%Y6!xDW;FPcYEqs8K`}f9`pPR1e{ry{g{BW&XFyzgd-Y&2v9E!I$nmR>d%#(i;XQ z*6EzKs8a&G9PVTuPH>QuK+I0=e!SPUz-O9v$pdMq`D{Y!r`@qwYldmn2?}mUAG`_t z6=ar%l0<=D5-RoQ?k+P-i7*ZL9E^mO_Rh?o#xKI=f(tJE$^Ccce@|SDWjQ%@8T%7S zr7OMhz4Cnd^w;N)A09un6qum6B>>(NcHxB7l4K{~;gy&;R6gD`&GiZ;13uuaD0fl| zN3FpXOzahuRV+%2VeJ;CRWGr?v~A^oZYO_w4v#(JHEF$zbP;51fKRe1gb~(jO3#J^ zm6)dvkp*y}t&)7{eb~3Qu9#e`jV{;6iNMb&@GnSG8&DUOww1^36 zQ0J458Q;##V0*8;EwgKRvEDXye7>ue`y@+UgnTGEbHQfKvwe9E8!^{yFYnkZ%+C)i z7tZZE-2c7~7SPey{JmL6k6&KeoePYb z?v#ag?IZ*qFRi@W-wB)LXbew7e5Iv0RQxfrLpn;INZmvYMVQ_ z9Au}5Ih-MZ9(V{&N686sOwKSOIv}0mf5H5v0SooSHk84#8wPzC0S%I(@f2YNe2dThQ7Ke zJ7fDLqy!fG!KTRcl^*x>>19RCe{_^Wpi?zRf4V3Q!>pgm7&brc<+tJOX4>u8vOzMW1E(^q@Q!qBBHFW!vIj1Of&XCV(e^!qmsm)wTPfZNqED#fe-j1SSB&na;FnF_2 z`S3Y{`ED?-dPlc?FbGlT#rYSQ56)MB zz)IVNo<5Bd!zi#D4+S8y=;M@tAw~`D1*(rn(Z?kvW5(?$&?r@dYiLhn(7z$+9%trnSHJP zI9GqXR)0_ZNLGKoR)3nSKhD+fe^mXBdq}|0rcXQ|6_duOdkpksZW}rD)73ucjh2Zs z<~}SBK)B7%7y@}=`1P{E8!_f}8Y^98x+ZD&AT=;8+c;f|&#PqnSiXKN*UevRxPGmn zF07`nm9JlGSbQzF_*!xCwa99pxCW%dOKYkq*C}@%STsyELZ8^c*(!mqf7;5s^T}SH zU*3Iq{OiM)k8dkY3P?*$RhLHv_j`XYp3^?c;y|#6!*nC0947k{N%TpQJqnNnP!2F2 zSohGA(#m_5OK8+RQ6+E^9c1YS2PmVk(1-AF41AuOEdjIuwbe?pS6%ZKX47G#3Jf=Gx`CYGh^O+NtJ5(ZV*s``5U?(zk7 zhAZ%dhxAN$94-uc$sQMN{im^GFxdvt8j=l20+Rz7X@$#*qCm(Msu)a+zGsey-mq_p zt40jWC#vUp+B39`1U56A7Fqmnv-p77^5~ zNfjFp`-_eCAeAQKZ|KM!IQ$D5)Q>fxFpPWs<@Q^<^F-T;GYiVJ1d!ptQCcG)DizT< zBv15BAQWTjG1lM_d@|c6H)8V-Wd@7*cZh*h9XhL{XmvQ4b%uV1YTEBK ziy#r9<2n6r4hNw7h+M-eso-_RURMsTRyNUW492Vgid%KNM%w(hYJW@B7QN6EJ`H-) z&6Umc8eI3`@w+eIzk7Xq{QPbj=XD^W|px_nXv%D0>P+1C5=zX zolgUwe~F8hbcjO00*p_A1Mb>J*@>{{1;N=2UM4C#9fS4>Pd`3< zoEFDGv2La%^2HM@R_H&HO09UQpjF$q4hDn+x2}q~_z82*r8MUObj^!Nv*-~^=DG#q zT?7uUvF}g!6G+%P+?VUtc-Qc*hs{}kt5Tjme{Czpt5OE56op2^wI3-f_2;RSX?3@f zMPFrvJDcV2u+9n|f#)nU!}$6pHv*b0e&=;|@Q6R)BYk|_P*gm`Vd+J;kZ6zi|gFORE{@pskMxiH!Z zcKp*|aov%U!!xCw{F9L!zkRT4jr=awg9tRK7o%!U(z_wWT`6{~5R{=yJEO|GzW>Zk zdA!vME@~t<>f!b0$H&hrLJ8~P5_3qTf0zJtR=O9`@b(-YWm)zh^DQmv6C~Hmnj=d@ zAp#j;K=6#7xcf*an4Uf0obhrilRH9`)2ssr(aF4gwBZ%GceA!?)bXA6K_h=8;;(o% z>5gfV8Gzj6lVF`oz&~l3elc>c83f%uKmjK8AIif^nX-5?s6p5Wc7 z0>oN)1$|6EXGaL#D}|5}SFHw=FYUQZL~z1Xi@d>D0P$Nl=z!4$R~eFF76-vS*&O22 zfpV^kdh$u{w42wzy*+<^_v6F+e>L`gW8JE8?;hoH}x3Uc+mt4uoN<=e8p-O(~;kH{!Wh8IB~3 z1f1e3m(B5{1%?- z6vV*MglL1brIz{d^ziZXe@g7$x3d*JYOMr^53NGS`n)Qksn?Z$dovrh=cq~C+&i@A zThhArBndx5OXA$Ox91kTy*eB4Is3K&gw;&F{F&BgMU@oV3T)oO3AwGn&3R^{eM(wg zRobWcZhM|j$?Zdi)itht#_BZNXKo8Ktn%vGvaC+4g||-#?InHte}L6lx6@{SeBR&} zF{5zwOfcw9zv|u!&N$I&bHNdh+I3`V(O_V~hCbqVcLo@3AZ~y}fs~o$IulzG#(GXY zYMY<;kMGTeAW*xbLtqF>8=IF7 zlX^{8D+&BOpSFF`oQJbeQUj$4K=dVoHDII|0OQIvoinpVLOKz72{K9IuzMoU2Kge! zihNHpAoD`y2m)>-37a3^i(Sthu2}(gPz*CUSA>j_vgx<`fILFYW z=<5wV8)avL-DH^N{o>fV9w$?PJ5HTPV3~s>d`J$_e|xz^`;ifyo*z~Wp5!rgEG+TP zOd1s28zJ5`H8raMFiqi|Jz|`@Xb=WMnKq&I=&OCsGKs(w*TlHBX80C}`?i_LI^ z)f7G?mu33oBt_0KPDzpbF(4iePr*qdg9aE~ZwD3KtBWntSDc0&U!5hXM}-`BxaMg8 zTbGR*;7GyIJ7ItW#jp!IGee!GLFE)_t44Ape{t=q;Un^RDtareZK&W>ZP#elRvsGLa5eP8Hqc z8B)J10|UaP9d#E3E9^?a+_)akKT}kzA1fb|v|9#J^_iGgZ?ayFGrQP%8Sulu5+t)D z$egnUz+m?xrRVwj3chluAApnUp^ZD}e}TmJW29>c_{}KD*~NDwVUit)*@Ud4Vcm&N zj0Y&Lf-A^FbRme#&*TlBq3oe{OI3 z@ev(zVfb?v$uf1IL{)nd_3zZX2gJ1G$`q?82!xU;o*B*`g0%JWki=+_JUo}G#MS)Qm;N*|0p(5n$nZ&~E}cGbW^-01B>b%EezqESx7 zV4;UbS&sF8#m+}Ec}6iBa%jlpf1mRjUA5cQ|0mLn7EziJQWfd^2A);apaa3Ib+O!$ zA~O?t*0W;WJ;`x}w;7lu1lciob%S_&dVT-A@xyp>eCEoX7U=w5hXRRZYic85bAmH9 zA{IAyU~r!5MUvO|7`6fv2Sy=)*Yuhi>FCacqIY66?XM|fyAj(Cs^rKNe-^T&VeP{; zHHtvkVYKayzt=C5Vfy3QdTfp}C{gc1H;kmU>ut$Oi9$;<)G=7@1%FbZ7HNi}Mymn@dU#dLHOalo zpem#cCaRS{e{4NDcPe!de@;Q)Bw=zA744klY)ERJgTC;2FqX`I7!~TtG$#ahJC_c1 zN+`)@2Tu%hXBEOZagYz4#MOfxWhA;TR+5jXNiF*7`>xrb{#wmZtlO%gvP&yRHC-y3 zuH{MB*LmMro{XkkhrKPI`o5<1n3`5tRh(Zt=Vm+ny#8&2)w6}Qe+@L@-Uy&M_-O5= z^ERGv1?~7V)(aY2TZQm_dqp#3e=9)GK@!1nEQ7x9Ois!Cm74!;sX0z#(~+O;f?@I~`P1ZOfY6`^ z!dXjt0-mDz8>(&5e193Ny9L##XF+oO&Q_hQgx0vY9B2n@q|GE>tE zyGM2aG&wbEB)V%cz19MN#8Y*-C^Ik!W`(2f|Zv)UW2p5Rs&xz#f^=lfe(-xL1{ z#={y+{3rYtGmObB!3YC8k=bI#D*Gc5AX#&Tp&a)5A)}`v`m#B3~oombqw1h@s)SjS3bSt6q{t(3B*RYpG&@Th((}7lx5! zH`0S9@xwHEh&|Z5k(|jOcLgusz0-E@%*|Te#c`8PDr8<~qoX2t^fpb?+M<{#hEsfz znuFpVvE1m`eSf=N#XyJQ@>0wt1EUJ3(ODp^X@6-uPf(T|MDEP!Tw^=V!fK}d^;;^~blvNEEYz)Fe+5={sqm4E6vf~lB{ZLV251C9x)J?upW zM1~ zhSF~(h;n7c0WS4dGO-~l$Q3b*xL*>Jt09#Ugn!c#=n=*qo#;j;#z9b4v45czvULWU zscBJQ?#|S-!G9;LBBuAzjlf<-6&&1uz=Dn(=6f|VsxK2`EpjFHL-r$Po{q;v+I2^Q zGW>sa)3vZw8|ry=`gezPYk06jtqt)r9W6&s7KCS z#!fiL^V{pYAD&;H{x9^AKdxYM?Y5`1+alj>&&L)bEJ5?lrmtHqdp4WG)w0K*R~M!B z8D(=ewra2Y#r|p9AwIod722=D%;G8x&3~^V=eo^#(^B}|gC z?S|(0%Xcd}^y#Llv2eecOm_&Z_7_eiAz;Tq=3~ktio-|h1~OfdVO}IQjC%o>&zTMd z(#wM#hu6g;yjmxn*=FnKPamIKSg}Gk82mx5SF(PGBiO-v!+qoE=20&X-><0634g~X z^|weS2WgJecj#!m))Arlh1Wt)BAvKynW+c*dW(*TT#2__buumNV7NvdP_SA-LnPoj zLl#yP>Aafs-Qkk$TCsWKXTMjx8=W;+reJ74hI7y>xnBwEGHvs_D&bxU+9GetL}Uih z?#_7F$rdLzcef{b%);z-L6X5c@qe=;#-&ojhw0}aG(0j7K8`zv{4%GE$8tsjfuf0T z^LQ(TcMlUY@@D?z>fdp;07E|C?q`f90PHM7aerE%mAzXMmh8UCrwq_X$`R z)TBi$+I7X?1VHUndP6w3Wq&{JB~_$lzR!n6j?RXOqG}&k>A=Fs;^*Nf2;A~{h_|O` zq4ZK|#7bX!-m~7KlUI0_IHj;=Fil5jA(C!&)=CT#vXWIgi_@{{qYZQ;1m(ywd8P@; zkJXZtW}8x|sRHv-)IkJeJEe^J@*cF89gsuGu7;yS9(`gis*RaAG=DktghdmINnkV{ zA3S%?qCbv@%7@d#sPANsgWf%Ni!sewUD!htIFm;+m8DcoWP{nr{F$GVY?F6A_3Qwx z;ePL+ZbeR*L2{$isKOOw!7WO{X%w$V=Ts+fmnSVK9Le>RSsIy&K^(~=+`uJ^o$a7Z z30X%gX~CA(n@2@*2Y-O4+)1FW$9WKu3HMS=H+5=UB)Jjcmoqxc4uy&YF;Kgyf=*)4 zEBH>Z>^i~=izM>I^EF7LRh+3=zE=twCNr;aB`?K7S_YK7@PCTr(o(EDjj@iOJM^X? zR>cg>4@aaQS^e0$RfV2@7J-M@!vJCEDW_<8{)YRrTf@$JNPqs80hD#KPd!@VmGo&f zunz2ERLxfuCiF` z633E`K*FS+Hd5YFdrfuoUYL}MU+U!2bfh{>(f9;~af8>%cn)V&lNe2tksgYjF0g@Q z;;y_I%A#0$kbgK!UDDHW0eWBobAXk^|DzaeIf6-c*NNuZ-20&8A`;g89`ZQ~lh?6I zf|X8+tFQ+NlNF(>tKjPn&gl{)SDPuO8fnC1)*vryNvyeh7~UN?5(n~Rin5h!1LCcE zw*0PWcTPN~%?BO82$@@bB#)U=u1qFc**kO&hv|b9oPUKgyIv=6dM}pRDpbn0m1o^g z(Yz8GBwoj8%FbTW&tzOBbe4mpGXg}wY&qH(_$`_9HrZSBV$9N>k0xa!1*Cg(m9UH^ z4eFSUWMfOu(PHq1_~}`AXKL@vZL(95G;Unv&~v0w>O=;$s{0pBHoB^Y4zzgA`T7Hd zGd{emB7d%#f3Tr@Mzcx#jsUKnv27g@xyLxt{|kExW(E8ixge9?M{gw5YH#|TCE(b@ zc85sgD-s7mZkK`d8}6((5FHUQcqKaVdF04*Mu<;a}Hx<80p#oil);bbeZqz+kf0_2r{Y{m-3_D?R=ci>m{~ai~vXx zbzY2{MrPd}B$vTL2WN823s0SB%(5HoDY8I&=|3bQ;b~#R5igogk_~w@#Ubh##*1VZ z(m;L^`Cl&f3LTrT?6I=r?arQ9-zo$d`9L{G>LTRC4JS?%^$4%pR?nBu?S{|79wJs4 zmVfTS5^lnX0*7b|#G#vJglu$%;tkbWI!2{29WjnV{s_U`3s*dvO|ndfMQKJdPCPZmx>dR7kx7k#Z zo6M3h{K~3n6uYWXT$R=x>qN|#4uVeiQh&}E`Wi+O4~vRDi>w@^v7;1~BL&NeVUDCQ zr)d^nY?NCh2+2tl;(f5Od0J6nIs*WaGhc=)I3z1mfWwAci>MWKisCcR82|ZlRtb1* zF*QvqGAqo;`lljp$Q4A;)5edd9+3RqxNd&ABq)h7!DF(8CxD$IaT%++GbS?38MUgfo(ky}5 zqA)(GW{lh{mR(D$6y01l+$fBMjX6x_x_u{Ys;S*`>Ls&2`O-wXley&KmVdEu!EDNT z+4AWPahzrz85K(DPHOk$BP!%!ordu1H#oD#Fh+ViS}>e@uKg3`z|5UE)t{0*9WAyw z=&?rd3Q&Q6-vVO}dKUdcqWl@;DlZBkA^$j&B>qkWAz>viw@hz1%bG;jcA76zoXgPD zZByV0s%1Fy|2sAYp2Nse?0?(g<`bVo+2@f@$8shfl%&G5EILuj6TW0X?7VeYj-iqGvh&2fmHx-Id?{iDDGOYX4E>OX?5PHRaR81RN@S6U}b-a+&t4m*DELjOMlfUpUx<5(vCJM zwGXbNEn_mHV-v*hh{8n?hjt_oCH1MpRwr6F$VIZ_ju13iiW@>JclU>Gvsue)XD4+h zAZ65<{tTKA>H2&*XftHK&gBbS^*lGqJJXySAu>@g~$tkeP?ifvd&ubS+=R|7lqs~ ziF=*)sa!-+k0o>Q#m?_JSamRSbu|77bWVGpJ%`j8(>oe-gv|BR7NA{>i!P1azpk8$ z*%78i?X}5_%Z60jmNhi&Cjt8wydz0O2kWp?w6!58BO+X))_?Q&;jsHvxs$tNCuR(5 z&eB7T9J}f9!p;c55*W)U_H>Uf&M|@o-n6_A-?#fT+WHY$H*#!!=a6SE&@Jg?Q|u9G zn4FmfvT4FZZ;Yy_b$-V{_9DA9xXc|b`zgud&9xEC!dnzi( zSODM1Jq_HMN`KhUtEzI=wH%ug|9_9~*W9GNNcb5hGSwnUvrJ7GzL(7-K0f|LWp~hH z?#KpuimYM11dn1*hN30%}OpI+7>`jY~+(to*C(rLcX?m{-?(?kC3D0hjv z7UvbH-Cu6!@VOPdxO)>k87=aZ6#08%ho2CW{&i)P`hV--aUVQT#5VCJW<1) zKa{_6rhiqWfdmk&c5GDd$wElWi$`Ayg9Nv{IwPZ)?mAoCbb*I3J0)k=)jOwm-OlkY za#=bn>BQa}Qk5X?XdJMU{|@Eb(Gz8BX!zQGYfETJt%S=jkZ)erf^a>x0YYmz5jL@( z!Pm$4UtU)En+ExA9hO94>PGLu11P$*fWeG&Y=3NGSh-$et9~0UejD_}SDvpqt_7+D zktR--29Xg|{G|4t#0>qGFP$2&4aqo*w!DEr|1N3wOD~t~PEOU~*4yeq)qywr&Hh@q z?AP}WHK%<$jFAbw-8#EQ3*@sI!2k=_M4>=Ozv7>^vTL;QT$}=c&kBHbe78q|S&$;7 zJAcji`R(cb3S%yG{%FptENLReSP|An-0Bf)xse7Hosd{wwqVxjFD)C+ZA})#Z?bLV z8`lvCvisz{J9z2FY!Yu>DObWGWX83TKtePvezt)?u8k`olW#S5e5*}_eX)1%pPxUj zLjyXBo^fGHVigmltP+)@G3$Dh80_n{N`Hf;mXYF)22Y+E=BJeUkUT%5Uc`GLlYZ>S=8NmLwuYk%(@>-Df# zmIGd(=fTs(cYtU`FRsNt?}c&x&LGgU3>BRjEMRyX43I`alzRqF>vv^=vc#n*in}Mu zHrZoRy{HDUQ=6}PgsZPO%vUKTt>8jpsDIZ{>hXWxKfOKvdkj?7->5Oi*_bmdh8$;O zi;ndQN5U|pThAOLhU?Hmk$-vqE(!rFUgN`X9Uk0izU$U9&He6m+Rg9r!^7v#zpVB) z|8#fxrn7M;>}Ds}14##*EfPoiUb)@JIj#-I%pCyENU)Rq3&56j+8XeAXDuYDG-Qg| ze6B4JEq>P-h%4A?awN7kE6~@-&*U@3FTGd~{&(%3pB}%wy|ga#oqrX++gZ4~odv$z z+X=X@t?=F6y4~%q@ZH{Cz};Bk?+5e$O0z!ix5ym}eXI4c-?V}Ej>iV@A?EDGZ|YDi zZPul|VEEd^|M~g(bBk>!L<<%?8NW$K)6FCxJ7v+xnRTvHEcCgc`0e9Ax0B({wg~vxK({Q&>ts8pc z>#R8^555MD4$+nzurx*Pni6?HC^|__O2vLk1hTVn)oFbq)Bf~0L9Pm?B}Y}U>03wP zao|TE^mokmn*ai6bdEu7!gH`2IG@pZg}qc7drI?}?|d4{P=9_DZMe(hKygLrq;cen zVn)Oc?l4yg^&!OWCg2D*RCJPrU})$ND)>+bqatZ|F|d%wa^{AT-Wd{$5)hxM1xPRl z2o{H{VjEEHj+82>t11wA<6hx0sLquo+X#ESgQ|kMcvEg6hlzU$mwp&3&4t zY!)KGs%leeh9fGs=nBn)Swgd#9SfXN*qucLus&Jr!XQ!&v6HGvW06lm)ogHj?A^S2ukiD^)_-g|~?wC*9(M=f)gg?Ok%0M=tDkbFr zcN6I8u78q{1C#W0G4hFsiamD}-@NB-D0j|OYak(o(UMWu|GJ$0{maAF3OUDVcKn_2 zs>lOr_W^q}A&HJT0tfyenvi^_`eChXOZM{cx{``a!WQ=FRIxk+YY^=1>AxG;Vf)^| zKAf10qEm#gF&bSTi7k{Qek{N2x61YI{lhvKbLw@OTaCf1`VqXH@qM_U&M&3!Eo^etznNCAAUB!ZUiGTKx zxGY6$G8Y*B2{IGbjA2P2*3eDc%)S27s-0z4C4rWnL#tLqUDjbBLyM)k3iS1Ok4VWW z&E@*NtB=99is`~Fm!NBI;P#8p0rm9&d=s`_gqs(!ZHcKU8T1R+aLJHM-OnYWQwzt7 zp4^O?_Zt5XH*d0cWQKPYK1b0x1Al29MI$<(b-5_Eaw9xaP$@xXIVltw8J1tlWd*d# zwvu{FVz4yM#wdrH!gIaFGEc3TXkoh4A~C|;(WJpJbbSqbW7Y!448`^aZpTSy*Ud87 zN#t^YEAN!-3CUuHhIp9MZm5@#RbLMHfjDKZ`jfU)#Uk$*o5(zfNYV#$rGIn1PV65| z(gV#-QCk#&-yCVk`A#8+qs2iE#y(wO;$obLNGlO>RkBV45YCM*!>GupZ+v;cp#g?8 zDm*HZaT1aa&>AO*04Oo3El?eqh;p7O2u*c}@?)-+>;g`$H>vjSUfNxl80s_ktmcF zlCa{AvASLvvtkY)4C{!VMYJ_JpggFTd|=3%jsab#6aoVgJKq&+j+t8p28`qy#DZNP ziU{+1p2_Fl6PIfY z2o@PKqM`a0+(JU%2LD3--&R$Ia3OBf ztjJr%RA19H5eWK2`yCVbhB?)P#%Is5?wTH(l^uYRXNS#-)-GZ;>3A zM@bEi(OixKv28MDwafK*=5&_s=VT_ag3`pLTY4bh?=?NP$4P!w4w}Uo@Kuj!o3>7m ztK*7Bi8W~)9e-l>7jub%t^zAb6S=HP#pHC7Cir2QrofN3BYm~{I#ZPHYqD6lbQGHx zLt>m1ydyVRUL1Jh{1WMHO^ovqPx%5*%d?aW0s;O^GvXsCM(kiM_M9065I{EW0V7~I z<+Km!8ThDkn{M|%?>|2LxE(_s83RcuLuS|uDPH9&ynl#oj~HQGvwh~%+q<{tcMqRG zuXgwQ6ew87_g5@+4-3OT%!+bWRD*V(q5{eCZxerk?sU>6g<(#frfZ_H!*PZ$*C%X? z_W8M`WTuJ_0)Yz$H`+>QtT;O%be%AJFd;=S10Gw()M>v|cQotGPHR+~_JvC`hT9uM ze^~=%hkw6d*SwGmyZ#hW>Ed_4IX}qTxQGM<{&^V~2)5M4&+Ta^|4ZDX~|Nbn=nGz2J6@VaSz7!(T(t&>P0+~F$hKpu`&q)%6Jr5@Di0j zwtrB9_J8-m1ZLoxuz>@oc)qVFAbf(it&&7Dh~&m4B_$@IT*z3mJffFPhY#Hoy_dCW zp@UX7eT+<4HMu)k(vSLN+`cthjd@2}Z@t&y>K0BK-!-1adPu2Mj!>a10h>IBi+m zWu<|EC;x2`>1$jjIxeUsNfGG#M(+}?(|-ef3K$u>pph;tcN$bHl>0|p^A7A2fZ;k7)4NQoHFCI zNAg=SItPhv!?S}j6;7cs%56JgQxIb7N8hfmwNPK?B&Hp>#1_#MD7}N&#tmT#On*NT zr7J4dvVk)T@cHHBkhGOGEkndBNPpvOaTYsfN|t<(Md1SOpnxf-)kV4!92PtaQcdiH zm9Bn*(KOjHIMVORnZ3y+g@U+Sax|^b%i8$${^P?ktuA*UB%?4-F(|W46R!3%Cg87+ zw`|tx518H+AZ+DImV&$fr9A1@u78zpT&rK>Pt}E`GJFwrSY*xUCS=Xx1RIW!k&@(= zi~DTeXhRdtv09WMlQc?&x?G2x~M0ct+Y9spGvM zl36;V;aN&+tqFYi_WJVcrLVr}Hb0hLcvzSVT&t)`oAHQjQn>Do2c9@Z}}FaKQRn*52vp~!J@0fCp^ zMbQx1SV&TY_ww~(_b1=4n>X_H;rsW8 z=g*7bbKCwn>Xf{zr?InO)QqhVrc#7H3LVr)Y`#DxB=j~-~ zycSK-7WA#Vc$CjsmN(WNJzUJJO!j93-;&rfvWWR}50Akf=*}I{f1K)pwjyFw@o(W` zhWh@Fsz^*ktUSUi(vMqs9{7c)L0EVmEWZb`4z)}almSpl)77iZ86Q=~IAfvDBn7vc zt*#pd4~SW4jKoFMaep%tsK7~tV@#Ihb4OS?H35ke=L7LF4jp7#B8iByqXVy`*b0Lk zr5a_M$~z30vy`nXw?!rpLU%r>#FhkhqmhU)#pJ8S8%4sG_bI0EFwi5Bg&KoWcf?J1 z$Y&;QZ7_7dvMIH7tARnDBXVsjCLq`NrU0T3Lp{zhE0Ge3(|YE}zc<^|9Gqts5RO5;ihQ`>?#Ik3|SdyH$@Sd)=xbCLP%}bFDgIC;d_j6A* zuzF8$VCHI`LfZ0{Mq`cq?)p@-J~D5o%`Gtvmru|qkK^Ak{`HU=ceBIB7t69})IL|@ zZr*CWDGPJ1tbc?8=BowDj-V)#Y=2M^32bqjHS(~=UVi-Mpy(fAwgEen zgAGDqBhj?d<*((VgbN|y2E_r#g(YMHH^Lj*2en^$zkhMs!b4r^U*nbByZ%$WBKTfv z^++v%Qf>yX!R^m4_RzcaLes)3b_EfcMN*xVTS;d0=AB8f4$O3-#e48C2MgvjvaMYe zQxrnWaS@`=lph>dcBTV6fK3w5=Qrs^Xx0ejh_YDu1O-u<&B8V~j>=3rWoagHX-VYA zMnW@Laeo5F45iU1v6^wa+V||c^qVA?Ei;2S`M~EAXmiU~9}db`8%rpJvJ4V^wk^dm znF7+GC>rc#Ip~Z23Y&?m_OhJpj{U_cNbPNG=y+G54GV%$)LbGirypi7I;T93LmNa2 zV2!hO$qygD+%L@3#7U-@0>kgTHl}LiO3$?cP=611*$T#zIr`yn($mYSQjaHrOu=y1 zG{Xaw&24Q4=Bdn05UVK&5FNE%O=FoK=6YX$Wtlm}=b)2KLp9JdG}dMT zJ3y61*@VO74C}Y^^z!4=-*!7n#WMpgg;F+O66Iuv$99d^tD9O^Na2ty0o-NRXO(tq z!hhc~3#ZZ`b}j8DYE3o6A4z(eHnkOMwR%21JUxEBA~F4yRTQbt;moC0Z~~7WSK-A< zS29GJx;Zz}E5umK36V>kTX*yF@yFMP=eNJ_d2fY76rfRJokY+O4Y)E#n3nQtRfWve zovZ@l+>(YApF6r6l)ppQo#lM^_m2-xi+?H2yY)81jG@YA<|6*sAHei+$ULX76r+iC zG9$9JwWGPOk++J*&s;7$Iev}xhrBK5fhrS?(8W@!G*$IOB3Wd!#wvCWGMtitv*iA zCQR#fKoAX?FM``(?v_k76ck|60<=uy^rvwf_@_X`HsO=ABuSVjsOlmKAyP;@+qhBN zo$wH>wbG&A#OlNT^7!e~TxLf-o_~OTPHTvE)RQ|XXOfLcPQ}mMg<1rvc4iGym3*c9 zv#kpPLQZbnf=#;CG4M}X=^5`t;iHgW5I3F?Y1iL+Hm<84#G*!(pzeWl7On&=givWd z!Z3o2((x02tbK>Wj(X%Qajgs20tR+F=&cylxT6&n!W#GpbthPv5eP0R7k`B_P%q;F z=;+}RwLaB&{CfZS;qMxHvZewIoB;XGj?c7?5BPGdmNskKZYuGNaKaStGc3PuH*WE- z?^&pzb`gVD1Y_VL*OcVPk&p&|gPHPHAjKu*Ijr_9PcQQ+?SHkt%%{wIoZtv;!*Kc3zmzb%$M z2oo^r=LnTPm9de4j&bk{(WkE41KnZi_6Uc+QBZH@AvPRYd$i~DaRDUv=s4ny5`KUD z_;^G2cn+r0fIl{)JUg>j5R-8A=GHXC{(s7esM|*MZAgl$ zOJMK6UiIHT{koWVwmYU+U9^%F28ED8UzV&EG|%((Y??Y? z`7Zus*)zBt5OR(p{F>J#>wBMBix7_3WO;E9FjNn6OoF){A$uNjG*WUN+m002U~f%v zeab=;^@!)jA{owIAqAo51V&^dpzbxI>`F};V^dx~RR1SZTN<#2m*yq`5a->pH_5W> zJ-08-VxR(Rd4K&xQ=n>)uOhc9UK1d8?W~B@HbRCA8<>oN#U(XgA8AJ^vY&`d=#h3O z61#2e@7=Tg%t%OaBL0*5oI^b5;6e}x5E8BI)qi@c;Xp-T<8z|3%1{mrSduq& z5MPqP*vVyY^?p}tJZC0QLQzUeUS=u`i$>-aq7pAkiYQj)&0c4qOsrIL*%c|-hF3-D z7q`>Po|K4SZk!pV($&#}oip&Y9;(dZ@UF`qjV4_|1PL)%7|yM6GbueKl0`CR(=0-H zF`pQtd4FANVKETD?9V&-#=`A^KMCYOSa)V5`4TL@LsK!`Z_=#`LqyYSwkqf?aE^kM z_l7GCyc`gP5+rsnCWrQ=OD7;iKLpO@7Exu5fz7Zt7v}`Kl_KvA!1k*am;m$3@|xbc z$=oX}Rye?tM=7gzF)b?)U>B7yQI@?KU8U{hmwynGDNA_rfCkCuSeGI)NMY}n33(gG zPBR(znJzXPC4!6iijjUi>S1a8!6p`D@`rXeZlHsvS%id>t04drH69q8m;D^0{76Zo zeF{{MuK}UR{CWVef?p5l&5K+qn4qLrg|!)HdIr^Zs~*o5%P@u9-ppY`K2}k9q~<$? z#(#tQf`L)0y~OAhnRBoWDwJE#5cy!k>>vj@j+WWW4>(b9WTu!A;iwfMve_;!hucp@bSD? z776UCHAnIs6p|?ik~Y6FP*~)^TdXZR9e<;6GE>_+eyE$v9UZIGrK$KO_AI;frjZEz zoZ1IM_5E48ZkewpJTk2NPjb5=AWnAd3}tN27dQ&jSUJmcY_2I8UcGYgb)vu!(4Hus z$3C5YS&8$N3?UJ{6`2`m8SF&Hl>#@t&1)dINEqeTAo9YWc0;ku0E?5tRc@P0;eXc0 zig?4N`m4dGG`s7rm0-^f#)3Mc6 z6WJ+-wWxt`*j=FWw_}_Y9H02pM1T7$zrPE|enPS5?fFyH4T=SbZoJD;RI@9NjPL^q|>BnMo$!pJX8jlG*Q$&(u$NjB8nb(K!56|MCt$?zq zTu{wL_-_d{kL7uLnF}`mbe#2OL5kN$#+6CZxPMwricDz$ z80w0{I919G%e`i#3tvmR-!(}TdR$ZFIukn#cNuRgWBeHP_f@uhO*$@=msyGGE?5cc zPjq~opRQ}~zm|xOJqh*5pR!8yn`mj*( z5A^4Tp*K_W_}+h8@rz(9S~ow78{*g*SZyp3jgFC>LlFZ^$hpB`TRw&05F z(3M*nmsuy3Suys!6NGJj==kkr4lDXg1`V{eL)|I6Kgiw=*_L3tga=~gOY!~4zF($J zoS`d0cCv8+Mh=rs=_Y@DPR1VhVA@_$03{~T#;L*I)~EgZ*QdWNir-aB4q8GrG9x%& zp@Yn!+H5TKy|B)gl3??~s7)TTuft`|;jujjG>AWcs)X)#t#m{G1shh8} zmmR$+$aA|2{WqD&V0|isb2LT59WX`Y0@9$ch$PCpCx$`H<3q(1WuLqEoI z&l;TO>-V?U$8QVQ_{3LBbBnGJNPqAs;&~}%=JaH%AzYVSW-{4t_4A;>ZoMKf8(@MYX=;DqiC-WUtj)h zF@eL>iee`RS&7%4@=iN3TWz_X4<R8AcjIx|KF^0eaamR3*Zjsq9q$|XoUo{fp7 zc7cChpyO!*S}GdBUI{cP$#qFZMC+hSx$herk{**BHMn7Efke@xCawRRCY!(@HK+=x0%sqT)S-dhSjd=rX+H6phJ2QHm+|L>F2!Tu#g*_2gkw#xPxc z1-TTfR7{oDLnd*99ZgJKrZh2ToA`hu35ChbjfcGHVOvWxILn4A`a%jt79-dq+|hru zlC!O51F_sgv1SbS1HxGy)&ElJqJ0!IlOr+!?<{Ag_(Uj2@>SMRu|~$Ea_EcbECzKW9Okn1B66LJxQFCxT;{**KF$9(hX=1 zN-Y$M&@gzAy;N!hz(tD}%iH`;(SCnvWh)^mX>_sGGsZ=En<1J|OR)^MYYNo&2G1Uk z(J$l+d^TImhUQUsQmdjKs|1j$5on@pvc+{K<36&@4|s?{;|88^B9h)+w)V}QrIP3x zXSE$Yk04=9&#!j%W$J)9j^B8G(u1^ZAt30Ru~7!RG78KLDoz10E98@)#HWA60CmS0 zVKG4%c2sP!?5ap6NYrELT3;#jq=Th%29lwoOe>iMl{!q8#EVSIEmEJP3}#4irV2EU zn!_HBnY2CaE)Cp4*W`ZN=U9W`wSIyz795vp5SDeEZ4vre~dl zqMCB5q|$9tj+=%+e4we>D1(2NxYyWYf-@8g@`I5eoYFq*d?@efswK}u&yqCWIt{Cx z?kr9uastV-0yTO|bq_3H5v-z4xA*65rDV;|Sve-Fm+Rqw5h-+he6T)m#CKOIm?ztU z+}OSDm+cbsngZwI&B~k%PL1^oFj_jCY!B7pDj4 z)!6BgUdI-Rse|wYNr``}v}JCYLUao1hn)q^g9Qa3`-)T%1nNMlMSgQ{f9-SM53o_< zjOFq-(o)v`ZWez*Dq>Oe7bCv!)r-HI#b53p+YVIiD8;A0P{NX+o&F+nQ+T}n-7Nlc zj)m(+s}uc|YkT7FXMguVh-b!!=qgW%Kl{76{0+7rf4zMU_7{Judj#-o=;XxzAt+jy zwFu0#HJd47?#LOVeXjPm+5Uc9yRp9?kMmQx-jul!i^B}fcJEUE0tJvJ%${NPCnT|94S%)o!Mpdck1bmmj4YROsW$*gPss%WI)1_FOJ32c&SKdN2~c9Pgh90dARX zOEx4Of9V82;^eK`6$h1uC<&IPn2Caz5ZB!vIEN4zw+rDpQ z%c6PZLq#Ym z3%d-6k`_#R6oog$@Avk1{7eBN{pDPZ;!guRNg@2uo9gjK`i61Tf|wx2vAzA}6jo*% zc9_>2LM*Q1<BrX6d*8lRf!GdO`j3vZ0kC7bVNp0E}jY}TdvHES*XRrg~QoS zp)5oi@}2sF1j8l zoFY-+@xY}+#Y!y#d5Y#n`ys5Du@xa@Gqz(m9A&yn^S_fR|48jNYLt`lj+8y5{{fFD zzmX9o4bypxlOjM`j8e0ppi&^P`yLM6OC@kSZjJcwNvib{;nn{qquMeSM6a3*3!J#6 zcL#HSTo_njn;N{)54?!EdwC?6Dfo3U=~HEuw&G?t)A-tlImY6`@A2A zypfX5;Qtghd&*k))%N%O%ZK|PZ!ZhNCXvLM>?kVDIek8w0>(keCBP7N4C)&JBGWlb z7T!CL6wQegG32_q8yto44C{Asl|GvnUTG+Qg9aizc$6&R!Bi6I%26iw9!xX03IrZF zzA@KvmNZ;1$Jm*DSn6`-E$4#cGM!Lg;l9(Ba+H~ZO#G5&S`?>FQXaQ23yv)IGk!@R zSHg)o_wpt;3=;$fl7}tBT8+@uv!9Q~0P24gzG(JUxE? zlNt56e`7dUd^8dPi}3bA2ZG~tNXFoZ0L?4&G5$Q+DU$+QQ>}GV#ClILD_(y;tUja< z4`08%{pn*T4=@c-29pVHBA^>c91Fm_T&#vokp z1h1DfAmaX7DIHDV>>mTe$7zBX2U=^fS2U)pf4#Sl^(#;N?d^3Dj2=gk^be@bUsTAU zE-yV@*~SE=5=9JWs37w`O6asG%GL|^R;0+lysAnNV7>Hq}7Rh{2`cV#o8eF zfA|eL_rKgPM4AM)lz0sFb}8r%nCB6!?^Stwf>RBl zUtgXV4qx7hQBkOhC17#mvbxFrE1fa(f9<*mCzlpC$u+USdP|^bxiVmnzBi&km#qEh4Fdp65nV?vyLZj{goSAoP$^~%kyeWi`Y%P zE3-~mlTz3;BrFn#`IqjxhX#^~;JqwOGQbA&kxR_ffp9B#_uCSnH}*Tgl}wUie|*c3 zQEEywK>WoK-m;wZM>@zYb_!#%*xS~R1lX3mFTC9gC9bLu`l-6W8aG5ypv8~=PS8rH0@M78;!+MiohFFR9FLXkz@C$;pSiz zc}jBI`QR))nn3iC1S^ zq3<*C;H%}J>S?j7>A-#KKW+VNtzV$Y-Z28Hkb_E68GOEax|WYjOjPnVX%>t-C(RLZ z8Kfyk9?I%Ew-hPYOxmq?-DTX&?A4O5+W*Vbr-fee00`fnIc8`T6H~BIfAFAS@^B@X zjEJ5zhPz-g!#o)lNjUBL#XsDC{P^-?0oqeX2yp4%0#ppvXGs|)Mu@T^>Ixh2fW~=7 z+O~yxu$w!NxS8*W{DYZ$Y;xJAJZC#ji~c9q$c>u#^zz&D)6119cb@mCbxlmg%I60e zJj!Pi3ZGV76+Y5D5ztLUe{EsyK){nBs72iv=oet@>h*GdetG!}t-0671-O@j`;BU` z!k{8}P1<}QLNMl|kRu{vh$X^=2L?$ZyPGXMTRxuMZcGBW((2U{rb;xcvTmdy;6BQK z!y~)WWnzih*Sd=|T(bU@b+RnxOql#c&m$=Elt~ zQT2_QLP@hY)1#9>-QWB=tSLib5@=MdYwqSuISJ{%JMX6@AXg^O%M_1z1SF0PbLyhs znpD(yBd6ahe*l6!wPe#0BzCRz>wz=y|8wtVC9r|BPa8W`oEI+ybn6y=%u8nA zofP24`Ljn^O?MwiP>>_H$-^xDR>{{2OprgkgU1)_?{B@|o_>5^&V~B> z{wH@MoTe}%>N|;5OYGRq=1Cb#H%huftobX;>X}y>sDx!^e*g#D2`F?I=ggEL%H20Y z!VlU>xUd~eD4`2|r%ua*8&#J@V(*fl+IK0zjT-s>cE7YC|C7hqqp2|!_6^B|vw#bx zSdc)t9mfFxOTLT%OE32R>(MkUFXJ~{`mHvog*%6*iZ8pe?Gbm z!n1HtE1gl-e`x#xxMsPY8oqqG;^=zFZNm;eQ$|T(%_v8;xDCcBLocZ~B+1)c@lzUa z8h6B`@NOC@O%ydmsC0VRAVr4D9xusWM%?b|!Js=ydcSw`=>_7H)6bOVou;|{{D82g z6+PAioFbpDI<|pO7jqN}Md{04qso{eWe*x)0^UvT9@viKVIh9z+_>hT4 zrN$L7o{pfVdfD1v_GNHQ1}S81(}|AiG$AFtun_D!tlrD7FR%Z^RR8&(3pV~F{DLq~ zJxKGQt5F2g=E;FPAxco4WEwnS&@$Za7Q2eMveBp=;AZ&;Q1GY&_y>kLE8p))N!qMj zu%xexe|T{r+;|y9E@N%RS%@jj95$}c6Iag@7v~8G&(U!z?Df9W%PxC5Vha-$=u?N) zzfa-`Q=fox3n12V<^k9MX|8b9je1=uN64UZ${gMTF%^8bcC=Py%)xOdd=039qtdKC z>-Q71*Bo6T2i#p>$5Sk-%2k^ge{Ap+%Fn%8E3d1w+(KFH4wQQ6DdL~+ zcuEv|i-Q{%m4!2&`t$wEYIUx_W;nD=&9S5aV?dn0O`N8?oC&{^NWv#A$=dPOH!qFG91F8|Ks?Q5*daR?96#tM6{FcC0?1E572I71)<0yy1=vK7M{2+tx5!3;z~ z)Q_rJ2Y-$yYNkut*fp)(^V=`?PcwmoLcl0uWJGvWLQuU7eodkd&=rFi28MCu7hi+e zZe+R@F(o&;>1ZrKdc8-7hVCfBL`qel0F+S-DW0|`BZbdZkZ402q_kRx^WoOJTOn)AJU;+l|781ao&0u09=`+*fu~Zx0>dM`yb!mUhkhC=Z0TD z-Ac!f6QR}o7ql*ngByyx|7@$EArHT$Rf!i3lfu@)EWHlKwhE>k*^fU;GLyfe`iDqz zoXH!bj>t@f*aDrW`|(E(Ux>No1C1w{rhhz~v!;bABNB%Uc%uF2BggPuBZU%%eJeHdT*&(9w|K7Tx4DRMCL%)#(TTeCuqsB#oolkqs{fiOJ8HM)#c z@O?AMDdc?Lz3%@v_B)Ti{_Ez2p-(h^Xyb?L3v)8$84?VC^ukXMzrMYDRXQ@vaR22Te)nz+-&;;mwkSIG3mNx6bHjYG4ZOb4E-(}R=tjm5r2R-&xXyB zq>Q71QxbXCH~}4p@q_kZ`bKPp(Dn4pL3VlE^4JM^p&JGKWn8>pcOD6e55#-$_gZ#{ zxsm0*{zHU(GJkiab;R8A@@H5uDe|Q0pfp31_{q);WSjkE;?)DoD_=-rxyg@@rl}^~ z(oF46GNg-W$9*%B%dTzDaep+MO{0=thBM{ZYR9p67;hAZA|^*YV#vjgcM{3pWFSx)h2EsCBbY{!WAcD0mr0NVloV-%(5dK`hJg7|ELt%@49c|;{mr}o5yKfKwJ_k8#c5xtdB2$Ho z7zA2Q9!w{W7U)&_|9^KDgp|{Fxrndbt)-TD zEw4R3xuWq)C@*&&NbcHyvKU_;?h$5n^P30%3lMstI~}Q39)J7lc&MV<)F3#H)>w59?;Sbhz{xh0M zIX`Va`1#kAWBi$Bv@AG54u0CM-oKSk4)0)p*cb#Z3?S< z#7YX&Z<#L|5#EwOLQ1U(woPWZ8%Ole3$J7w&VS4 zK0g1a>OdLF(o>Ly_ZqtqLt}n1E2fU^e7OAJ{qlT!`7zg1{{1Ev&`Bna2Z@e&cXY-( z$ZZ8`+JF46={pzzQpS(pdGd1+);~x$#d8<+95ds>nCWl^6UxEtgb29G^5QGzEE%MF zt8eAm8-bvrmO5>GD{`BfO=evQ@o)P9ovR>{0A3J^?^DQCaIrH=yESjL* z9(S5gtV}6ncUb)UMOb_JezFMjD;-%cnH4@O-8c=qRfMsc7xryHaT7G?v527$j2Yv~ z!+*{(Vl0UxGXK^zb9HtS%D;cR|M>X)d2tO#n{Vcx`LXe1v5y6xxP;DIiA^W@^fADo zJUMsL22XlZ5ZQgV9B==6T1>OYF{0u%M-w_K0d^;5NxWlHG#}Z8^^O!Xo8E@m@A%>D z*Ik!>-Sx_^yUMTo(n7HZO_Z&NO=Un?D1Q)c-M4vvqXSg`9#=@Ile_%w;W{34ZXy9{ z?V(@1=>|e?X}os$xhs8t`|!(;r>BR7<#b`!dP3Arg65a`R5?-?dJ!v0(I!9jufcCsF>!Chzq~OGq5J9S}bn3pU^l8D0&hzBr>@fI=+0P|)pa~K}P>%kex z9eNFD?#c~ztQ)lHv46m)c1J;S&VP~p?OyrY{ZiK!*oH9IGZ|+dlO1vFk;@Fk0EeHs zB1$=B3ucaQ{EUDro{pb$ay|7#G>X-mC4IgB{CfZG%VKa`EEi@;@N-X7HI)iRAf7Kb zrys*MTi0~+5&!QWFK-Xm9_T=8p^a!UNANpDhs&L`Ft9(#5RUI3ml z<%Q^7MTQqcrU|T*6iw+d&=`=`Z$=r(rX9?!q%d2~-A4%1QY_xLmFA3zppzzfVc_7) zMaD}WerIc_?)O}Kv=xSady9KzQU){iS|ub(xi2~6VN=;3B2didGHG)!&oNKm9flJz zYlWa_;J{bQL9)4!Y#OM*Hh;(>k=l|`YEqP(jL{@lxy`UOlc72H?P_K>*k%aBV$9Ux z@}{HORU9eK%-&QR4gu&)g(Q;gpf6hG9F^roNkSJ=@&y%vL#Y~Qrc{6<(4nnReu93P zl%uFQ@0|(_6p;pG@^EPc=1K((F;BTOC*~+s#TbC0%B<-F7k}D84iYHi$zw2w zI7ftmY5r=P749TdJWxAH@=p}#qBdkvD7H#ul=8C`BB_jiH(a6$)~tspuQpYrlg_KM zbGdFN_i^iGc>Is$6voRXpd(x{7j2rsvCCuTg!a9+f^hH*_~*mhm)DmcpT8_l9`Do- z1u_E**MGEh;L<(X%zy1775-D#SOx2Zt-*6E-yP{2=bc2CQzmwg$#$B84^&zoTf1V= z(7row9V)>X3D#uPS(RM0C@$KRX-4h(r_{o#!9hwqP`j-N<@W2hM4pA*qOSi+mD3RCo% z&o1%aMEW0kD}TX~A2;6!00J~?Fl2NgV#&z`HWSArY1~S9lVoZIWl{&u^T~sqSC#@M#g)+x3+*ZwT)Kddk!6ZUmkT2q0 z@^>u1@#Zmpm}oC?_tXf008cXOWkLyMf84jxjqbfOBY*6|{p|S(_j0C&Q0iU~N9vnz zEV@N;!)8jv!dCmD!Q{j$yW?{_@j2dXY2U`#;D3KxYu3)HwXq`T5t>-$OoA;eTkB$% zqSgf^b!%Kv8oQWx!Q4PCt3R0`ZB2B%5_9LRRRs>uY*q5o=HFm#DwscJB%{?D)R`g^ z*uk(h0e?Pejmb0NNiAuru1js2ZoxbeyGu1BZ|z8h9Y3-Oc`CHxGkRdQpJ45Uvnp*8 zoTZin{E;;rz(TCuK(E`H4U(bOYO=W!G;}~ivqpo-zzI=0YcjVwre!LUf>CUF5>%wY z8GZenY4H~((w9CxR?}<5 zMq&-g=dW=2#^#<}6VqWipw?Cwz+c1TAFT z=Ye`4CVj&2dcC=fMD=}oeAPty!xPjMmU10V_GgT&B%3#QPhl&IVkw}>977Zeqn+0k zSby>4$)~ox84{Y8lf_<58c*_&nx4zwUOxTX!|U7Q$A5Dy^_Q2ox0kPrK37rHU~Zzd8_(ej#5|gr zPK~z`f9@*Rk?FdX{izRKwIlN~iAxyj+VKlXj<5(!A27ai&d0f*Ex_B$x5d?YX44FD zc6F|w+%YPi3RkULr~hqSWq){lUOwb;RZr$|0ibESlB+k3niC-kKbaKgwZ8xFAAk1? zm3@@gG0{+1_-lMwHh5VFD^!6MF1A`keO)jFb&4U#=iL3J;PsCe{Ou}O|NG@`i*lz) zxywqq%U@CMmv3t?$L|&X_s;+0>rzV6&qGNdea`tk2+|((Qs#w-uE#wpjHDZ%e6O@{ zJ;0;N&!SQI%}UXJyPum{LMZV>aeqL8e55stSnyi*@W<;)69xE7KsRcuX5lgj&-PoY zmNY;W7#}gWRsOeEpn@Z2OO!}HZ41NF=Pl#<*HDo8w@*X!hb$kY-nJZ zz*qv1@a7dY=3{<$*&3$z48@z=H?_Pn=-&TTXrk z+8!_lnAr9rU4ZCzgu>JLs({W>I3=W`Q=$cBs#{Jh@mJO_Fz_0m9^AX&9*%vmu1gny)$q_Pp+f=pYp*j6Un1B4q~gMqMd1#{V?G}t+m=FHT@ zQE0vjgnizi!Z$JS{7C)z+-;UVkM(VOoAi%}Ina+%jzD^2u1NcK_UQATRlg%J?B_ZsemWXY2JT?_JigP*1tJS3IP82d{^7rV z%0srLWxz7AkqkPJufzj#6sfRcoNEevR+6A%U!o>~hn0%)cd83VcT9({ITVss{Zr+*N1O& z?mY*%W~%nY6@MpUfBlK6NUW#z>WaoHau5k;$oxU%Pz*jXen{-XD)vz~xMqWIzFu`BK3`-hMJ zdIEIjb+L?Xh#QcOHSN+Pv#Zlxl~da|uGrch99up@vD5%zL* z)lpf$!&TQx_+123`@@+AROLG0l0wV^D8o(3~?tcSpj~F|R#^=KK1a1>Agt1!F9O7#L z!wDDACZVt#N})b__6#BNf_Xjy7YGI-hL;0hIf;N_-XqG?`=ixv;hw}jts{yI7khoL zKRz#3bD;Rvy%{9Sq;5wi3Fqf#c2jRVWXShXhl-QCA)gtEE@fgEk2_D*qs`BoeW$BZ zWq4BSlwl;(RR#5g-M?pf$>{ zGwWg5gbkd@U@1g`8ZZq@e4Sr9d z*;1WGi+wW`eh-=z1v&Gc>*XqsQf|>|HKSv$BE)-3e*~tvc8c4_zEzYRImj@B#$*Ze zmOz|=Z8mR)8j;{(4FG2K-IECkRWNYDO`i>Irk-smh)ZBizR@Pks_g)kv;zh5L6?-~XiMp`4w^q>IN7gzQ$KD7 z_T(Y^p8XwvmhDu0r6(7H6dmNBCOHcB3X_zDpRzv8Ze{*`zHy(+yKM5U^Hf`P(vxsq zA7BAax=*KnVp~r5E@FjKTo4Nc2rTS{H$3hpesj4T<)h0rg zhibQfY;iR#<7JS6Z4>TDVkN zvMh`bmXXnJr%J1rO6w=$X?cYrPi@3Q>GR{SSISO)P3(RyyGM1$=}Zc> zGA$dBt!UAEE}GB_Z15)}{F#3UPqi&)M{&V8k7=57v~tKFD><2;({UBdt#L}Y?_$f=1a1O(JsFqEOA3?HD)^oQ#HaZV;pWlS+$5sUS<@6bF4%L zvBwlT?Ueio7-Kloj>3O7vr8MGWQ9&n0!6?R11+bV6~luR0@7xn*cPnxoK$>Lv#BP3 z(C3zrobT=4&9IvNk&ZE_m@ouPVvBNRWY&Ru=PzQRGqpKnfO&o z@e-!&`Yuiad0^{5E_fC^As~{v%6SU_B$kE=Iu?*klcmnQjbvI?q1mRRZ+j-*FwiBK zOAiTFsQ#kI+sl9Teuiy^;-QX49Z?pwCPZ1KPgw!Zw!|Hx(wEH*qe%&K>||T}zOj+! z8gI_T!7Lt;i0g#((ng{x1mj;eH$;dLttKxIK)c7O3M1)iCGFgFln7iIdlq&rH=6Lr z$JdWntCDFDgR;R?8$`{)!=C8=u|lg64!jHK-=0+>$unZ`AJ+J&g_YupX24>_QySG0kd{-ZY|SBG-+Ft7PoAMY@2GV zlg2w~(7lOY8hw8eE-%OVeVM#N(>JTXY?JqI@>X76)yexid8=pd`uY8z^a(h_71;}dbu)BdZNg9Dr5l*x*4d^%J%(_HkoPqfj0yKcK zmk3oN%wI%2J9?Wo*JR2q5eNEN*{tKY$yVX@K#~uls7Bs~u1Y3gC~L z)r>koDZB-`urtB8@3aKNwe%uF2CkQUFjde1w;Ku#sNeK<`&12uU>i)tQ3i5&_nIpu zF3<)wRe?~(WfBNkc*)Q-`WHdCW*jbs>hjnS* zcK`f&rDdU9_2kcY5>K~p{_V%p-i(oSxtyjSc1?`c8InCoYdIk4tVC#r#A*6lz5BT|1rqCRARtj2#u zCgm9sCh`;#=gR|aQbDFLAZZpou1xCIe6<0V+l#N!6vL#>ID}DF@9^RKg5x#pMS&VX zP}X__(b?$CGR({I8JQpHpiv5w7_|XLL0$H=;?OGKGE~g~uEKwJm}O>uR6>!S292Z_;Q3f-#PIdIN6_u!KXG zZ5Rm^u)ei1@7&dl637bOGCdTin!ug`B9w-J9y#_!};w7#MS+OUeV> z_u@W*wrxK9GSZVn^V#AsMrSoK+_L0NOF*anVDYrhV?Baz%to zR?4Y$2%a+rX$hC@kh<#xkuQ`@vC&F>eicv#(WSyv=D^&0HJm3=od(+MZG)jgYcW!} z9T;|@Uef@%W*N52Q8XFjN-lrsXp_PL0tL<-F=$<#2ZiSB#epUB21yI0+B}Ict-lhw zOTH+Mr_k%;tPBH_GJI{QZ#1kZ6Mg=A|M+xm(=v{(@`C`Td9 zgcos%0})gV6$77|83-mc7cU{L1u0#;Ctd{0f`AZ9*qqOKjMxIUbWhSS*8-xRaYaf3 z<^Y}e*1aSen{%S-ueE<>LZ}<~h#)A+Q|EkQ=$ZN^k}(cP5){X&?Lp8t2>R6aM(0LP zQZFRhlIe$`83NOio>?~d0I)qt8N{<)jip5>9<^aojel`{2#w2V_d_LEP0)HExi?Nh4Te z-XnBN?wKKveCB^90ZYP>GI4|KiZY;Q{wSB7Y`Rza0{i%&fJA{vBPFlKZ?2y&tPbbA zG#e|BW!q7$Z@g1d#9K!v6-~q#jO?Rl-`?vG?iPF;71fWe_**U|Lt@1eGD#pq<7S1KX=-+2!_Dd^X zjRigcRSb4;GeL=j`EE2@h|T3Hz_FHUS0qck>j^~8dihJ+ z_8n);@W!AeWwzWvIpY-u1LX}txdr~J^;6Y;{>y)LZ#9}Pugf7FL5eM>Ze^7Bx+$2?%g82Q|ca zN3cxetSa^7!i)zJ?IX=D5|>CEVF+SIqpeNx&pq+j;|xHu0Fiy;ah{EJi)^i%Cv*9A zn|^;3KGtt3tuii31Px-MkC5p`eQmOvu#`Z9!Ga-RYp4=dIgBO6q@nIRXDQ&AZ4Bnt6j0C#wXoqvxp5)yyw7H} z#c(rvg*{SuDQuwqy``rIW5HOxL22jnXRGs7opze%E$7@N(Wc?hG6hVbiBCTh4t@E| z0dfAlBR&NaiGL88xjTbFc)ww}mxGt6AOR5qk0zJ9AOTGU{P?!8yq66j0UJeHx=fYf zaLDCjn#sns<(E*#d861|8z}pSW;W$v#J=fY;Hj9!~$;4$gEFt+U+bEZ!Aptf5 zK7W_mApt>SN{*~enZQz1G?X-`yj+`+rb6Zu?&?^C3QDKW_m@gB>3a24?~15ju!Ss8 zwJH+^QjtaK^;aZ|?N+{!>B`OD)ML*qt{q`&qu2Y*P0OdXLZ@Ejd)kRod5GK{J;G!e0qJH+l?0tCKA6U-u@7k znFW-2Sn^q!9`0Y? z<|4D>!n(^8LR7U0oQ;qX$-hqqB;^XlSPUN#MIg5 z#Ec1V5_m2o$5hL-3_Hy-t8G%#j2x7(ky$B{<&E2XB$Wbha_P(+PD0zh&H1j5lH(`g zN_37ae+wlB(;05$V$xAnHQQcinw5e1OJyLz0$^yu3D1u3eBm4#LK>z*x)Fm0Vk0(7 zq1S3;MvPerQo7*KtS$6V^=$s!yhZ+z=A=azG&;5t6$!zzBS=7rF?88v_KPvO=FP1b z<&l4KSF}|;%Ty3mD_SH_EwF+F*NnNm`cg0c)+t49*CH^rn%Psyu}cD z;nIk?Y{bUo8m5#zGvBz5UHU)2##A6Mn){bZBmo@+cj&~!mun;e8#6;MkIa`u=#anJ z{A4}sb+X+^$0VWLBZS=2|%1?8xbebKPASD453A-&Fn^-wT?&6m{B>^8j?&;Gt@A^@3zRS*a zqh&mggTgN}mrbC!h~O$)`d>@B4xRhhDyUkRH*$=P8&*x-Go~Nmk*&M}fncrMJC~Uy z0Yn0HzL(!60XhLmml`GkJv&uBcXI^G{SaiS_j(sZ+0S<7Tg&8c_n#Nx(6*(zAf+s& zUr6%_Iy+KDfO4l?g9b)!rQVmxNNWo}$d{5P0VRKLU;g!-+J(P8{IbZsU_#pYS$*Zu zjVhfS-dcB^s}|}Ip_7)w*7TH@lhOfSlVV%LVwmDs5f-})WP`SEKTejU%Lt$}yU-!A zEPRZLy0BR1=#;K@xf$KvQA6O8h07R3$3QA|CW#2ls*o9MHfterlD)h;&#Y@XGiOYM z&H#VRObZF5r*Mby3kGVi_TN^M0dp3V!esz3B{IBPL9!K2c(nz$cf76sFft8Ked`$! zM>xIY;Jj%-Yr8ldb8x*PGfVH!3fFyGAXDY72HNX_Y3<24^TxH#9M5vSZ2P8T4k{Xc zY82HfHGXXpkl4$9tHD0qFYJ}^!k(a*2XudCLo6~-hZxgSkQ8=~MZY_2{JWK>#&Z-CAt*P4-e+ YX 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

6;BSy`3sO7CjRBR4^YNMx)|P`@GQc}B z=tiTHn12bQsd$Q^L9U~e#&JY36-S1;}L+XCrUjsW-cLQ+q%Rdp4S^QbnSKk_0>nxJg^#s_68luRccvn1r_qA5dIhFY!_i*SGA@IIkCu3PKdZ(vzCTtFe67tO>Lj-QbPg08QQ4%&TjGx?TNvjQwcshIU~gKw(RQqu7!Y4VBXvPx>D)!{R{@^kQ6fL4upb*0DnY9z^*8cB**UO zmO=KNy3~(lQ9EGILr`JNrkiK134|?(k_h-V%b=|Xxdo9J zBH>c=)0Tr+kCK>WN5bw;qYh9`V;6@p`)NdStHTxnFc**XsR}l2_LvT_@d- zzrP%=uTp`adq<|j_MsFcMa4EqVAEByW>EO@Ui^NnRI57cjs(0&Rt?f43a!(3 z3>RqPF3j^Za;}X*OoAj&^IoVo^Xd?;hR{aeTh|l~uTX=chpq}&D~2Z^#~6NQh&Nnq z2*y8~IQH3X%Vo#~!9jXH<|j;|nh4hFBMXNo^~o)k%9JN9?!!S56ybR`bl55?rLh@OgbVgnpe zJe${q_^m3G@5RkNXfNqbAtFuw??W`m59TYeUbd?a<1txoN;7$~;ym4|O5u?(w8B4=+`rN4ruw*exYhnIgjDQ})#s;QKlWO- zcjQCG7AQt`Aih;W-rSWz#$%_%W(|zOGsHO878)$&g5+IK6*Zy?DKcot8AdclAb)P4 zu*SR)KddK$w;dU}=7R(Y+ zK{ZDV5bi&yB5lE)R7rzi*&VUP;wVQwGAD4U^-HhT^6zm?owB}ML<_oHSAT>Kbaj1r zvtQr+{P^&DpQ!Fcnxy88BIo1!Q-3Tsfl#88Zaj;dX*el~6k@}qFP77snh8#`zp*$C zXGj#^QBi>m7y!^Bji51N0M|8A$9SSfa3r7&M{olkcoq5cCo!SnKKTa)QH6g5N7tvE zm3&0v2gcrV_FFP+ zu`X+e<}ovGymD#&3C7^CAb*utC}ihK5TRJzTu}`AvU34XdApI`y?^-fu_xl0e+^=) z*(jGial_ffds<2BE7IVF0?Yc!KxEQodx1|m3kpo$w8@SW{romF6~>c_QPy1u=i_Xv zAhS0tF*&ggi^32mOVFFZ%F6wq56TOy5|gc7M?e@(JWBjpp`dfe41W_V;cWR$Nr=3p zq}VhXO@6q?*Ih@eCT#f2{COYwYaE?a4zo|B!d}2dK$R4ibu_oolofcxK1?YR#cIIZ z%nMPL6LHXN7w+9?t&8oH35WI#6-_5;hb8o*w(Q8`tbg@$G^Y- z`0(l1l@1APut1_@(i9Fs!V`lu`KT0Vt3JaN;!~ zP7!i=b0@~*ZZ~aq^qC2pj82Zu$S~1L8Rl0t7>%uAsy$W7Dlc z$$K@};|P(cb}^NlfOJNt`WY+_xSJDw>y_D)g96te^nWCX7|a9so9?9o>$lRja6;j* z_xS)C=96T-4_btmz=7c174pk3_G4f(d7~e{SuM z%uBXEO+oTTf(uNyWZV9PYY!OJMW*k?dRJeBG%AAiZw|Y!@n21?%jTT$x30gAg~jl& z0TU(YQh)uznKv%S*>&hGhNEjAdqo3K^&qqV_d8;r?uAR~saSexN&vnnnW>zjB`^z= zUPVPgO=+0W*RFHduH&t(^Zd2*NLji0czply_#gOqzWZ5jUwXA|Xkpb{;l1%*BnKmN zISRI}qos9Ja^j7g<)khu-0F}mG|S_kMy@XN|9@^)C4cLRic{i3HYB<|`b_)7ca|o8 z#YllNM3wj*CZ>zuKyzYmsATm}9jfPNY*p4_z9*%6x>Xj3KQU~I|J^LS%4)37>-{|P zj}5#P`|8@$r7JTEkY1V8Ef;XC?Ktw5c3c+cOI#cyH^#6tVG2S>qWS!NdtvFuEGscs z?SB{cJ6iQ@5Hc8^ghr?)pfYa~xj z$@}vU2Ft38I^ysUs|*LU1P?i$ZCqa=Lw`eVIHCdIqAd8Y)ceG??u=;y{i$qb+Rz5- znnsH@19GJA{J>NQPHwcH$T32Gd;K{QUG``F zo42CWof+ftb;}X|SJRv^%1~(^YXdBXza(lD?KF^}e}~*J;2^SHL2n>K*nXPtuYb`k zjG7~|I*DEJVs$~1ApP4H5~j(Q4}mRR3U}ILQzn^+75hmNlZH2O6@-4O{CLScdi2TS zmpd)E&(#O01Yzz8lzPUt=XZ$8mIb^USDAmYf#vgs9>saJAsrhvQ6uF=n$G>WBhZ4f zcewwess>s{XOx1Yd!uUh^S)+TQh$>q!nArx*ZEp8%CnP$}*q zxzk1NEJKirLj0tCal8>_I=Tr!B!neZDS5u~1AxWA6rP^5B`yC z1bHWcV2DW@h5ME zB;t77F{z&3Zvy8Q^9oF*vwhZd%M`AQ{6u`_1HUt%t-VoOMFZ6u9Q;-wW<{n)AE9~( zsF-Cgz|mR7GJ|97<5HMJ<$vp(#iuZMoTl?kf{-j1shSTz#ELv7_O_!1JCN30NbkWy z)Fg$X2xYK?0nUzM#^a$e6cE5ZGT!DbL*W*`A#22;y^uB_oc)M=gXkZX;|kI2+)ZMW z9JuWtWzVo7lg)m8lyg*+(<6ML9A#o7zmkY;k@h{wV1M_A(GsnhSO|xH zKB#*8w)M;VH9-YJ_UnLk7s1YVm6I;5j6xs3GW&8%XT=iQlmN4I6i1RSGfiW3LM9hE zy^+Ax#DR*%p%UXfIzj>!A$QeXYR4>?FQMlpgxf(p8d+Q)JC6CUFQ3;^LS_C+5*@W= z@AiK$3ue6&<#0UKw|}4ge=dh<#b6;H^3LnMZZ>r23glQ)6PzxP6Q!jC*IQg-{u-_X zQ-PqzjhxU&C}#oi@*jJTdN+o5A78$`uIX;Y{Yxbi`uf=&(3+sg$so;HN4^)TR16oW z6lZFl0Q(ej3mwsxx0YZxPvb}Xa=MH*ug;XevpCV!8nyOr)aXwEReeRrGG zO-sMb;=V3Op_pFnBN?MJZcwU5&xi9{EIB)A4J;u{L5S1bKdki1F|`+#SzXO%;>bJU z_|m^lSAbt%&FFVHPN{%?p@Wpv$6%uYKX>Yi?<MXxdZl=DKq$P)-ue4 z?#HK#R97mj&C#OZ>A>`nnnf5VXE%0(BD4&`uyP*Ref^&x={WsJa(mVt${|8~9-KMy`V-GYeS3C=)>&U~9Nn#w(@dhg<`Q=d%w>|p&189wZhV?ibP>$YUlu8qF zjDL*)h>vs)O}a#_Tr)e1rG%0YCsVdIQL#_j(j(tlGD&e^B!#A3KB~zU75O(oO#XQI zJR3BxPycxN^tGp27`fieJNt_m)~WRAfC+FEJ&h-cd?qubpm4EU{NEm5w>%Da9%>I@ zm4|^1E63B2%6yQ7S`paesv`oBZ7B7Rm4BoMQz6)R*;3XUCvszyb#x#)A%x6PNpze* zx>bXfBOKPvWM>!@jgp_>uSRDyv7!bvk3? zOR?Q>gc6K!JWyz%E(|v#+7@hWvwuHcdM_Qb$|D5pg8bj&89F-=fLBJWnJ39JlZE02 zjtPSH2ZL5h0H~7KNRa@s@>ZU2YHWouE@yFrluvX|&y91;OdwAj0l3~pzpAp?t820L zKxNaITc$rhw$hd+@+CxL ztPsjtGE|#7guVCQk^6CkF?($zfvRuZqq(g+lL+n#JuK`XFF9GM7ly`4aHC()stt5Z zCdG1K_mpUi-g!YcRU5-pi+{PnjsaQkS^H3Y572!+H>xY(5~XN`_Bhai<;bCoVJZ&R zbY00Oae73er49CkxXcvA+@F+?@5uWG3<_i=;Q@*i6C(HbsQAuqd#>Zzgaw9+P?Fd7 z%eVF`t^Ia8o$z`;Dx;9yuH0_VZpXf*^?AB2_-sOe^Q{SUYr+#Ps(%p?t0?_0+6*~k z5Jw4O56rqZe_v2mLu=b~Yuj*VP6e7)t#Q+>ag#Of&R0YPw8X#|)=olUO)XR?nYEFp z!Iu;I;UnVCO0FHz-c-TPM|r7*kRcAiH3cX9pA>-r-Z)SRS{s~|nr{6J5Ii6YVs)Lr zG;z<68HNFTRNSZmV}BCSdorgjN?8wyuMa=3H@zU$rH35eSDf+3rMi_QmU?Akw`ir5^q2WzVF_qT3N>p@ejO0So{)ScGoeWlcQt-bbgw@;Dw@^D-#!1#Wf0{2XS0x~gCSc55)r9Z1g(<1$a z#WX=B)}|AcOSRvv>AUwY&)CZ)^SY<1cGZs=w>D4{n_*NMs;w zFtnU-%xoh$(s*Ve@2oSdyqt;WDi=&S67)y_8x%<;C|mzowO=29UwJ|4w{$WG!P=y(B{Qj% z*xCtIUQ-SMzdJ;b?8JDAL2PG*nTu! zafuM}gqYquzXoyw;Z!hxpS!&AR*xT^zOM4d1g(n9T2S^NX*-pSL}p7R9%0=T;A24i z*m#b0EPsg<@vREq3wKZ@CIm)}j)9#x+@2`2lL*d2w+mHeFi~>VuUsOB#OZmw@XoWj z(!2f9JapRLEHiRI-Ww+{DIxX!_?(B{c6=soB%mHmmxunO;vPru$O%9$?ERK~et2Eu zkNw8OANz3vSL4pt6T8~^xg_r55#I>n^wXZ6q?bq2~g2v8wWYTi$ zVShGUJX2f>+3zoGa!@Mrti*Yz!`}VTez1RzAQ80;m9FJUp2{|#1((q4S zX}dm+D}UGeofykR{E0yvNtFwuqO+x=^T-5{ zS?t!{l8){<8jyv=KjPQJ-P|mm10;3VEZSYOxQf@^2m?+_(W!(L3z}%?DmDh7Nq=6w zsp{OnVd-7PnGOxz zFE2aDR#4#ec6+qu$_oz@ZHVY)^RUMBEL)E&stg2n`-cr<1nGH?Ye=5%^2Uq3{Py(W zdTBz}oK6O>bo(F|z?7@d7w0zny?@=?=gPZBhLn=Cl7+L+eJc^Bx;oH1J&Me!-6cku zJf^E7e#-Ut|FX~3+Q;a~(%S9QdHV=mdE-3soCFc$V8Q~8%+Ue32`XUWp@e2?7=_D#g21&_kU%~M!&1} z$XqF71Pn|wKE%fCSLkiJ*h9y5{mvWZ{O;$c_s{#Z5_!g3ON=v?s3G6I-XEY*ZmthTQcS)AbHpOz<^3ClJ-&#ujvY0+kuY2qI@9GSj zx%PKE0-+6ND&h_2jxhd#jxhcYI>PW)NBAcVDM7h0SoV%7IMgiIr+;k4kUcr@x3Yk3 zN5wW+Qy4NJ&_pXPnKYJoxWSCQwVlCSb`dfzU1e19$$h2qu;knRL4N$)*4Kf%CL{}2 zUvsMsefs|K+skh|XN}O>o1%e2Y*$8~CK|TTkZrW=7Jnk@XxfdFxP$Ov`RTxg;($so9)0EU(yHfmTd&PuxY@<}2;;-n zi)<$$B9^C+ecQ-ynG7;U1qFKPbK^8bU;wQuMib>Bo|}FfOIB;?s#%}g`nl=5C#<_i z%fh#6ZZ!B~3)}%sZ~dBMfKt2TZ<4G3PsRN2t(a2{)K9kiOleWLVh9d;ef9aQQwb)d9=49g z_`sMdLH{2wXMbE*`|B^y`=DTY6tG^b|5DKzLf9QDRwM3-hA(S?tVAvl>6N^rgBv<5W$u{n0svqrLT_k2s^#nN1r&>qkp+xkgdY=fb<2=%<-hLKH6`E zr?1^{n5Lbn*X>Nb{qY->^|zO;XSS8h4^P&|4LE<>lfN)u0T*!t@Aq=<)%tIG``m2W z@BQtETUX>;Hy__TQ_MW7F+&fO$J<+wF5gA1g5fsbiZtB@LF>eYh4L`+eM=2x!?ZUf zvC6}E*nbj~Ci`;6?TM|?9_wAnq%5Em^mbSE^8EDaFE7u3-9>GtyKd_>SGaHHX5_>w zK$hBg;4bVmZG57`o!9E(qg(pKg_AR_egfNA|DLXnL$s>Alsm)8`$qs;+SQ{BgWt}; ztZR?w^T+33UUxJ?49RkyA5BjW6bMuhc9`lB(SH=%gt=--6i1^w4Nb)wf5)I?pHm1( zD4RHl!P@>%L6qfaN;xD%Qe(3wkzt&$aL9m}kc>N%E{wr-W>d`)&($PrD@R|4f->Q4 zRHZXYeW|<11@}ftO}^pb^6|Hd>Mt)}U%q_a0R&oe0NKIZRcCBL32WtWcvT3*7_NCey63%+9@$r@$ zd)t^5T|Nn`*AiqN9*agUV#X~=eJqs2O)XET*Uk8+V=BF3vWBQ^Mbe`>srn_L zRwGG*V49rR(3ny%o1`OzN~d5K4AxuU+&F)0U#4XFJd@(qOMnvjK2zNL?7W*Ky$;eS zbvFC&rTmfnw$nM&j~GkBhVP-}M}I9DIzy;It-?-Eb(U#1`!m2C3q1kwAF3!&LH>a& z#ep!VkYBdTMiii4Kb#`-(0ha;Di*&&q_TRI^vPuR5Uv}xDNbU*hY`zwfHZ=$4pN`a&4L4?aBrhn;qJP9x> zd30g~0bTu|Ht65iulf4=v~A-`>OWds(JGE@U=Xp@gqaFL1$d63Z)=o4K0W~Nx@8%C z{r2wL_n&r@`{KV-p5qxeU$X>PzlEnZ<6U}iwha($do}4*@ppD!CLR$4QV1C04&_&h zqlt4@-SNNs*j^R=k{@>i8pN3lU)W? zAYsnyB3c&RUw?i2uqC)s)Z+*t9ezpKw4JaD&z&D8?Yj zq2P8@>5n@q^>h`<>>o!BcH_lgFgsh>3>pa zbFcxBJ(NwAS1Uw3SbxlJ%gdENP|GWp^?#Rg|LM!$b{XfTidL$mw(%0D_>!Ayz4FPE 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 \ No newline at end of file +var r=t.propertyDataFromStyles(n._styles,this),i=!this.__notStyleScopeCacheable;i&&(r.key.customStyle=this.customStyle,e=n._styleCache.retrieve(this.is,r.key,this._styles));var a=Boolean(e);a?this._styleProperties=e._styleProperties:this._computeStyleProperties(r.properties),this._computeOwnStyleProperties(),a||(e=o.retrieve(this.is,this._ownStyleProperties,this._styles));var l=Boolean(e)&&!a,h=this._applyStyleProperties(e);a||(h=h&&s?h.cloneNode(!0):h,e={style:h,_scopeSelector:this._scopeSelector,_styleProperties:this._styleProperties},i&&(r.key.customStyle={},this.mixin(r.key.customStyle,this.customStyle),n._styleCache.store(this.is,e,r.key,this._styles)),l||o.store(this.is,Object.create(e),this._ownStyleProperties,this._styles))},_computeStyleProperties:function(e){var n=this._findStyleHost();n._styleProperties||n._computeStyleProperties();var r=Object.create(n._styleProperties),s=t.hostAndRootPropertiesForScope(this);this.mixin(r,s.hostProps),e=e||t.propertyDataFromStyles(n._styles,this).properties,this.mixin(r,e),this.mixin(r,s.rootProps),t.mixinCustomStyle(r,this.customStyle),t.reify(r),this._styleProperties=r},_computeOwnStyleProperties:function(){for(var e,t={},n=0;n0&&l.push(t);return[{removed:a,added:l}]}},Polymer.Collection.get=function(e){return Polymer._collections.get(e)||new Polymer.Collection(e)},Polymer.Collection.applySplices=function(e,t){var n=Polymer._collections.get(e);return n?n._applySplices(t):null},Polymer({is:"dom-repeat",extends:"template",_template:null,properties:{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},sort:{type:Function,observer:"_sortChanged"},filter:{type:Function,observer:"_filterChanged"},observe:{type:String,observer:"_observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"_initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"_computeFrameTime(targetFramerate)"}},behaviors:[Polymer.Templatizer],observers:["_itemsChanged(items.*)"],created:function(){this._instances=[],this._pool=[],this._limit=1/0;var e=this;this._boundRenderChunk=function(){e._renderChunk()}},detached:function(){this.__isDetached=!0;for(var e=0;e=0;t--){var n=this._instances[t];n.isPlaceholder&&t=this._limit&&(n=this._downgradeInstance(t,n.__key__)),e[n.__key__]=t,n.isPlaceholder||n.__setProperty(this.indexAs,t,!0)}this._pool.length=0,this._setRenderedItemCount(this._instances.length),this.fire("dom-change"),this._tryRenderChunk()},_applyFullRefresh:function(){var e,t=this.collection;if(this._sortFn)e=t?t.getKeys():[];else{e=[];var n=this.items;if(n)for(var r=0;r=r;a--)this._detachAndRemoveInstance(a)},_numericSort:function(e,t){return e-t},_applySplicesUserSort:function(e){for(var t,n,r=this.collection,s={},i=0;i=0;i--){var h=a[i];void 0!==h&&this._detachAndRemoveInstance(h)}var c=this;if(l.length){this._filterFn&&(l=l.filter(function(e){return c._filterFn(r.getItem(e))})),l.sort(function(e,t){return c._sortFn(r.getItem(e),r.getItem(t))});var u=0;for(i=0;i>1,a=this._instances[o].__key__,l=this._sortFn(n.getItem(a),r);if(l<0)e=o+1;else{if(!(l>0)){i=o;break}s=o-1}}return i<0&&(i=s+1),this._insertPlaceholder(i,t),i},_applySplicesArrayOrder:function(e){for(var t,n=0;n=0?(e=this.as+"."+e.substring(n+1),i._notifyPath(e,t,!0)):i.__setProperty(this.as,t,!0))}},itemForElement:function(e){var t=this.modelForElement(e);return t&&t[this.as]},keyForElement:function(e){var t=this.modelForElement(e);return t&&t.__key__},indexForElement:function(e){var t=this.modelForElement(e);return t&&t[this.indexAs]}}),Polymer({is:"array-selector",_template:null,properties:{items:{type:Array,observer:"clearSelection"},multi:{type:Boolean,value:!1,observer:"clearSelection"},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}},clearSelection:function(){if(Array.isArray(this.selected))for(var e=0;e \ 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 ed3a49ed807e769a955c602e0004d5fdbc3b421c..696d5cd2e51185ad3e0467ef8711c065e6df8343 100644 GIT binary patch delta 94995 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 I8UnBf0CiWj9{>OV diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 8a2e2e37bab..670ba0292bf 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 8a2e2e37bab9db244a24aec570453653a0c2d4b2 +Subproject commit 670ba0292bfca2b65aeca70804c0856b6cabf10e diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html index 296b14bd858..2f73f5a782a 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html @@ -1,4 +1,4 @@ - \ No newline at end of file +case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){"mouse"!==t.pointerType&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&o.DomEvent.preventDefault(t);for(var e=!1,i=0;i1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!(!t.shiftKey||1!==t.which&&1!==t.button)&&(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,!0)},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return!((e&&e.animate)!==!0&&!this.getSize().contains(i))&&(this.panBy(i,e),!0)}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return!(i.animate!==!0&&!this.getSize().contains(o))&&(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0)},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a}),setTimeout(o.bind(this._onZoomTransitionEnd,this),250)},this)},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),o.Util.requestAnimFrame(function(){this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)},this))}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth);var i=this._map.getZoom();(i>this.options.maxZoom||i.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document)- \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz index 7b1c5b24b8253f6e6d24d42eebed458450beabc5..58dbc7d9e9f10cd7086eedcb1a3fba8159c36a89 100644 GIT binary patch delta 35948 zcmV(xK?&0_Qb^A^AhgN-=`^>ZFcLRx8Yy3%Fp^Z+)t0_)K+VkNE$@?A) zZY4q_GC?1j56bwtMuQ(^Bikf4@|*zLDbZ<7fRR&G-TX1R<@pZQdbbwnGD_Q1U=*8+ zLKsFhox{$_-@6rTi=ukX?|-HyNP=%sSR&uTEl3k~T65MQN70aJR2^?zp(i(CK|}ir5TZ zgTikrVyLB>2DxzhqNE(l2e)j=C|m;W)o)e3?Drbdn;D;+41YvwFhd6yijyuALfc}D1O>o1abasl_fC*!6LADu7ck}ZcfwCa zld+cy>%6DK!6>C;YwrghLty$lIYmi1cXx5{UKMRi1@CH}w;YSV;a@mRF!8qi51aZy zLg%x(i(%JY%xvYvfqVPlpmUo8wgmvf41y4ZrbrVwx;ZQ(VSj^#z>Zez*?ewYg~H73 z&u@qi-Xo-}$Z}3lR*sTfR|}0!97HN21{JYe`bt|(8Flx^#9!zu@jt(R!(q?W z<$JC!F1;eHy3C=y1u*1M>lXDMsnnM7+_Mz3IRep zIa!UtZ*?H`MU@Bdr_r3FPt1(J73lpqc4EGn>0?T*#ebhFA+zGz+1w9yB7#tudygHB z$LdD$u0&^OHL*=_G^^#D_MM|#j(!1wr{EQE{NDr<69`4ZyCFw18L^4fbP{#A7)S9$ zD&&%LcA+Lp*@ZDotoRFoMf|u>L9DYb=|Bb;!3d5knxWJ;w+^1s#IQEpGq$IFC9>k) znGT$f$C6rprW&FI+Atsg%hAxewjKI_xrg#yWe&RmuE7=F-q=*>5 z2$oS!h;fo^P^5ASsRG5{3bLVZ{2p~-SZ0Yz-+x-^<1~jGd4|j_btC#n6f${zS6xy-} zAY&8*X6 zSrzot`<8Zj9e)Kds6J?b1`ONJv`Ge3KqqgUVU_T&gC z%r%)rH(OeerTQ8XPh)LqLlhECP|sg@4X1uv&!Uv6CbYU+7Z3}XO7z6fmOAD&@<;)s z0a*QXdNlQTk&cep@fSBI)PEW{YK((L%sTcK(KA6;WB@}mlQ0Qn8WAPqXkL7QEo7Rk zCpfj?fST1(fUc;*(C^ZTnf%IKpb(+mgqYE@D8#TdzUhCPp0uZ_^*RU7#$*^J&Ebou ze9DzMylR-<-JuXh7LZEZGFrG~g@yV)T41e(@Aw4$Lc`O57 z8yUK%f9ReHTRG95PK8RU38|#Gal+uNTSEESb)+>|*RsPbS+_)T-}VZJLZYg|)w!vn zB?}csd@4hOdyCZprX{WXjARg~dkrWqJ4n&fV8&tHD`8e!Tz`-TA9IlUi4Jl3iMN9* zBrplx4Dxb5!0`^~$=Fe(s1hM0PVE;^C?K?A6{KN9gpSW96>zC9yJ696S*pGJl_u6UNl;uqsFScj zV%GC&PTYMX#@2Vmx1Mf>47h|D78-|i8A4}M9kl4cBASq+5bkP?;RfakqoeQcWr3FY z&gV!<=Ou-4UeUpnh2)ni1BEOm_N@86SgrV+{B-SGV}Dh10bEINQzZs=6MgNUt7zE^ zcdJ>)5j}u|>|SO=E_p_OSyO@0JY=y;%qo-w?4i2Nr)9lR>G( z76-#prrY)t%AOQPujnC{f`-D+BvI(lJX9LUMcYI{kR^s{*%}=Mh_>CjvhUpeE%cnJo|Ub5wSAWPd&EG^23I$GdmQ<^1%`VUalYLkQ<9+Ix{chLXlZ=7=KR= zW(gZTey|p#)jZQaevpX&NhhG;B1sNsYM&O_uz8@hopaX#ux5*1$2l$8vO|toZh)mb z^TwTdPELZwVTnGm@bAKzas8myAx6+;aEM`X%S5dUx(yC(-$GiS$zwLpCVU9{n$6f* zHkwSeAOBhM6iBP#aP@RNO?b92OMkgeplDC459}r8w8Wg27*=q&X6u9OEaGx;S4q*Swb7|^OFyU&*0jRwwveDy1<@x!5dzi=bjw;AAsvxhZ zSU5&$68PKQqoiCVMQmF_W5cyNF|Q(_UZ0sW!)3{MC( z9Af=*6=y^J^i7FWx)!Id>wjhDT;Qr*vpv&JAR8Sls#`cKW9s}qvJ6wRG&$ZN9 zT6oR@aLluQb(}Fs_ctnFiBRCz~8iqsjkXi#W<8!N-U)dorVpiNGEK^LhjM7!iqjyx7Gi7jc=0y`cgEDb`q4s zdY;=dvwvz-aO8R2K7Z$MkMNEx6C=vjO-p0mJVv0tEqmK%7Uth#oM~MW-)?>ujKLf3 zM+K*C%~mTNyMQCvP;C2S(j2!o{Rb8EU1P-hSgql$xIt1wh+Hd2Yd){@ua@yPe)cX2 zO(wQ+h}1qAFIt66w1~$Z<_1-(TqJj{cDz9gqX?@9wH)1QGJn9c0iTeNgq5tKxEM2p zIzUlCf(|+AoS4u&2_=&VTh{nt%bJt&RBKyoNH0t@e=OsS7320x^-+Q1-#o)G_C=C- z(t3MlebbJM<|n-IFedzQo{p0P7&{wIjE=1Xu|~mWM2(Gjy4JCKNwji}Cywq=fiAwn z%R*2ugNp|%b$`x$sD8i6({|)z)Jq268L4>4M#?c5&}I@OT8xtZQ)ccO#T~kaD8@iZ z>XOedpRX@2`n%?vtYBVj8+f<2cm_Argl}oJ%WdK9(UVCJKD$?j3Sq9$C~FDs5>Kox zeL>hQexz2x6MlNHe2yr=b-P#E{jodPny(u{<7@n}E`L#HM`_u~X>f_*mV$r(_WA9b zEQ-2x1(Fts?;QV-=W=u7aF7Hg4^|vaKR`1X2TO=e4mw_Pg5GBy`3<-BJ2Lqq!lraH z71N;IM1eneTF`?nws^?*ct7+~isS)ayQM}go>o^+p?6NMsIRam$}Fj|S|#zK_Fh~( z4Y4qHcYno`kgrCf)c*R-C1Qq*P_#6!>WM%T!7K%ANDL#e0Bv?9#ldTmow_Vdh_95F zYZn-G2rNMfzi$_uIN2s{ggPnMY3L0b*1&yra!L{-%V}8ZlUwmn)wFmb9+bkLaBGPR zO=MnAOO<&ot~AHX0i!KhN95C@S}*6%xpV@+iGSq6DNHKK7g?@tnJ!`s>c2>C^HEdP zZ5*aXMkbhTTqi^Be&35`m--zL^)l*Db$&??f=D9}9}~#6H?}y)ktSV?agZ(O0f2=a zh*YhAoa4*rOB?SPBw?e>C853U3UySo7^ps_5dJAmoyngxvtg?MFw!R zJb!p>eyj5pjv7M-O9S4r!bGCHub+&OXSsfgkBFhldUPXFZZPFW_kT|nCEM@obIi#^ zgB&|r1&PBelEt5ttUNWMZoH(8%AhimZa1TmL-uBgQ6a=Eh*HW&82guem1_AjVS8%4 zBNN^)KFL{qnwV+HA7i?n+*22Nhz{vOf`6>a-zbvs2$@A1Ar{k=9>?&!NZgfn+C-$q zfUU%d1H|=Ip18ZaQl{R(Pnmk-p$CG*D$xVS?_MKtaap#f(~TD^XF&g_eALvl`=sy6 zJhtpRt!G?f&RjxAD18m7WG+~N8aPI6wD^DZz^8kj)STTzW{V2QRMd-xgqB*Piht%N zIBS}d5}fd>ReMA6*?}AK+~L(i8Eo6HLsg)UTFSO_RmJveIJRvaAWv(=;>~3T1)W&< z;M5p&!DOgiNI(^xS-HKQmE#UFDlH?upQ_qn1f8o{Zn@?J@IdMd+344h>iEdN;K4#s zp|~wbh=_tse6ZM}OInu{u_ChgS%35@v$e9lAT5XGD9Kq7Bp39UogidJ3&-WVmr`mR z^fZxAFkG$B1Sr z68zyIp7x4}bbM41-xr4e&?|EEhil6y09w)0dievxx8DTD1D5<-j|^H7EFocwDTNG( z2G-7*V|t=I*zHGpkkX`QH;iMJNHy=sZ7mB8vnbQmmIhL~TFsXDH2(&rudv zmywI*BkOPp2?Ra4r=EozEq}?r(Xc`{{iAYp!y_AySw>FSe82lm! z9`>h_d9n#lOeA?yAtwrp9m0YJ=4*D;1NN3%jYvWn=tVx`zao8KEa~B?MKPaqd|t6d z4Y|bHou|ZvbyFrRq10Vv(D?gO#2tYg(r7tZWDu)E#yJNz79J^Z*?%cryTocScdVtz zSPXiQZ;wdEn(qHr-2akt?ON(~h-GcGX1L*y^G5fIGO$DrCaQXfAb0H{oyZWT*H9=9 zhYfdPa&&Y0f^)bmDt$*|vR>j_+MR*(~yYX&T zEz;ShSUxT!qAnDQK6+55oy1amBsD_f>-4tBoA+N!e3FXSfJ_@;A0r@3(3-b_^IDuV zrx~YLC8^q1HH8f6->x>iU(XATcD(pW(`L~^q9pY3tJpN>JtU|5k=#}{mbG@Fbb z9@9+HsDXdI;eS&EGBvIdnq)Z8r(YxyhN{BmRiOEPGSee$eL0@mSMe0MO~e9wEezpK z3RYO`HF@@H3pC3%4{0aMu&=LNBg-wq%cF&yurr9x>_EK7C-vxtY?<|w*?rXYy(U1G>V+fzD;Zfz3M z=Y6{(Pa}vnD8fGzeF!4eVX(c(Wmds10x(Ue8-r*aW~qB*%#Lp)XlJyz8)#ZZ&DwNq z=TLqV$$$C{M4_2!X5#spweT1v0s;w;Sn(wkq!Yrr3yZYBE)zhwhNO|`%fFgOV&$^l z*!VsG(?F^b5j*dNQ}ef*gK2xM-YbyxR+}c3)RQ1rr%VL z!ha|vJs{>18?yebk&&b%BXO>q)R&2vyQiClH&5zC-KP~dQBE0bXlgc;go5T6?n1T7 zVI!a7Xo`hISX;SEwCsCS$L?2kd z+ziEy#_=KqJJ3GGpMI-)iI32$XS7RtMt{3&AmJW%v8cB6JLF;1zpzF)zGGc$+3mIA zeR>Vyy61=i3;zXfNk>wSUio z9S3w@SOO)BGLn?=OcTREWnR~VzYrBDq!i2;IRk(IN24 z6MhgOQ-JSk7nxdD@{HDHWT2a8<$r8Z)fmJQ*F}8cU7|`^scf&<-*3o(u(90ukd?(F zr-3ZzI&rVJ}ADK-?lEK2mm%!ZxADl$J;E6fuImLkN&?jdh_4tb;M7?8Sh z9;Gq|tiY#gl`V&SX8Ur-+z;r`gxQp z@dY0DUbcr$Q>*d9NII}*^0R{;ur;#$IyrjG9!*Y}+4S^eazsfK^GK($;loF#OhAyR z`DlX0`d3HZ(qa}QRnB{0yUPfZC!i{Aen^$S> z3#128ED`{l=Qp1PS^@kxtBVx|NUF2LlfNJS-&1+cPX0dp`{?ZSI6nFNSMl>f^7qj{ zn!g_(9|{X3isWRhpQKMctVx;W=t~d4&8n<~!-kQnYh{`;K)IfP>ge%!gK&JqQ&S=+gZ+&2R<1qBXs^328N`F&DNgJn zv7U%2QDb$htpMJxngYb`*-d1MPbD z6x}(F&q%x(Skk1KOm3|*VkbnH~4y=S&JN-_BcKT4G z-rfEPP$=&^ZG6*d14^wp?%~_h0AEf%A2{2QMID0m47yz+hC6-obSG1L%3#X50Yyx{Cz%({SLk>5Wiw!MU zIN6E21KAC;;(z-n0jeeQ5~tQFxpswp;+R-5vTAoxB{GrVL?6hi!@|~jVMVf~hH$VD z6duD}9JDj2X^pH#vYJr!X8#0fPwdOpra<*9t=N?zp&h{mjAemEO$^IGQ8`y_vgscJ z*I=k`i!Ls#p0{jP(o;ORW46RhiWRMy2L!(~a|_}G{(p8ht1HPbdf~varY|Q#Va7dIBt5cfKW5o&aPEO1+49TcSU!o}+}hSgqX}&97Sl z(CiBKuYWOh{)69qz!Ztw^m|R&cv?K+n#gy;^NGgzmVkWKNQUW>)ci{z(fl}b(gmYi zFb?=7YdYPh`P7R%GI(E4{5uPpwuHHx#ywHqL=3qE82iLQU`<=C&}byT%w=y(d%E}a zbtXnV*N?d)gsa?OqK>d<$4C=HVz*wjHr7M(S${k3EY9R1^1yfvzW~nF3Bo3UZ08;} z#O(W%!)AVDJyBbZvUi&{hu^bL>Yi%yc;lv~o7(&D^_u>3l480Rg65zbZVI;zby4(q zulA`91J0yfQh;t1ZOhx|GVL@n*5Q*#K(H}_5|+^BCohXHQmnmAY&AJzlcQ5+iMbUn zo_`l#hC(F0Xs?!Jozf%GmSW}o{pjWEUnRsUd2ZT~3Zh$U;z?k&RCt7a0f6pJjtk3Q zQ>3Sb>%v)%&Mzs-eJm9@qw{?B`z76hiUP=nvXl^V4x$5{pd_LpS#rUItSmvXWmp_< zb^xgu+NZf(_FnO#+!rZfd<*FAir1H134cj$XUhtozyQYXeJOA{+3cX(9;E%L_&fA; zQTmu7@QB|J$76;vyASj_AfrB?uiLhw&q{E|Cu8>gsVeqCyx*IiJZ6ti+3%dMUY8WG zd~aeyj)=}8f=-K4(U9=@+(A^#_PN1(XHUESx3>tYKmaL30&qzWxOV7GXy)jIUt8nkcrVxjNj*$|Z z_3ld;PQC$39I+a6XcRcH{(gzXKYz7hp{oBwVmwD0CZJgJZi(X|@d1OK+pjSqk+i{r zXD0G#be*zoxNwh{uPa>Zj@=LB@ullf;+TxcA$eh%6s}<#7i3dkQDD)8YRQkQu9&+{ zOeVM2d)FMva@G*cCni{-_%)y>OaiLB$)dug3XeUO)09jD&T{^}NH6$}RDW1)Webg^ zJT}T)R#Zbqn##OI623lEzh|4xn9NvWDd*qx{1LNsx^%uGl!cN`*INL2jUITfwnXwx zBE9m*ktG3@#zJ7T|5UeJDe{D0&&-v5Oepd|qiSG2NDLO1f&hQKN~1#t+6vMA1Cy2AjS z@L$UNd3!ezbA=SL`A@UDS}vUh@Ei9Rq;Yvf*3ZWoPpsAUP%|)8C}%~uVRrp3)uKR8 zMqn1e)=uyqde;H1Py8T*ZjsK)SRm%)QK%vcPc!Y-0UnyJfBe93-+zH-!$gA0wd^ee z&4+0@9R9t1iHkI`JP`?V>^or7J8H5cav!D}V5&?x0R6+yMFHFj5EdLgG7+{T7244z zV5UW82eI`+u}B)HFcEM4GLp5xU@OvC>|i47NZcXdx3nmUA{Fdf4n(}2%9>8p8<~-N z$aC1xVFA=P1-7qz+J79!##}{o9uzR<&T~U{)C0`(uhrj#(?CD%r}s)-k~@dY*{W>Q zS~G>@nR$ZO6-x+tLWl40MBi3OuFgEgGtOijgbxUh(YL)*NZ1zH0fhpKb$FBJfLSAZALBkyE9m6?FlFOpnd4o>OWI4y7<_)G&f#D3w-cU`-#xJ0d*LQa_6mToM6c{(K ztMbVO?i>=Rt&vgt&JADXtA-6cl!P@H7U>3>6UNoAs=BN(C1*fx?-teX)g zpdGCqO_242h1dFOY6P_y_P5gka^Zm26vrnn5!Dy7#x=412!&vF;}ZIhXj?WPg7>hr zBS5;?FU|=Y5Y2?rr?rUg&0@1vwg5#nquAZhs%;vh=v4!rXr!$!FPFQu;tXD{;&BI> zluf4^xqpdftL$Qe#?C?fKw4V$VVP&@C+>||>qsC&>cDmlc5h*nyK(tJR=%R1N=oor zH=f~A#9G`NgE$(5dg$lboZhU8_0u{w_hT)rvE)#;T+CZGtAriU7=K&&y<;FNjnEm! z7*e+Q)|&{~>nSm=^-PdDN!Fp4#(VZ*Z!PmGDu1+9d=mi2P09!6E)8{Q_N{MYz!%+wP%(p!+|=+A;e9P66U!I3pS4|Qm~qea`tQd+iQ5LTCZ zJb(5WoEyX~<^?s=>2j><76_b(y*;|2{NYN4hBI2P2;G-Ful-kVUAXezJhkS)Y+-y+ zeyM)v;Rt*gy_;(x(*_O{7mmt#eMxa38#WQ<8Qh;qQe^(36ele#EdGnU_wpvjr*mER z^c}Q6*32|`ur}FbmTOmWR-$VZ`>py9-G8)qt7(&!&bp}A*_`)7PYT~rUxC0TS-pHn z)f5hhjqTTt17o2Ofj(60k?ax}U4T#=>5`EOz#&06>_P%p)s>-kmj;FPDrF6tlX}^o zcn;ZIVLp?;Rq+a)x5cbUZ(sfT>fPs0skkc!%3x}sO{50OKx&|!JqMOZZ=e-v1Aj|H z(}NQ2MKknaLL^ig<2$K^Aa;=saA!9X<5U-plpETHP0lr7omn*!Cp?OMamm{kyVbX@ z^AUFo+w~=FvGs|-q#t$nEld|ZTC#5q{RxZUqBd)Haq%x(JZr!^te<@tED|Q_E{!5P ztkp?36UkkY;f1RTb2dY%0Wu&9 zja{$?6%&XbDSyBqX&q*h#}Sg>5fv#DCd~Z|yTA zF)q1v^;)-_xLEeopxGC1UVk|I@a*Nw*YAGz7nx^%6u{%j(GTPFh(81pH0Fm|vJHoO z-6~m{{15`SWH?CqsREf!#%~}P*yihTO;vIv~*|kEj-y;&>Xr~~=D0x=U_kZhKm&Yyd#wpr_ zvNsrkbznerOHKWW7j1R`K38mKi9M}SXh^WC>NfZeAL0ZXBQfs1;7Yoj?avjX(~}(~ z4v>%?zroIG&11eMl$=vya&Yv(E+qy2D{C^|Q?jg)=$t0>>DQmn-hIlVMcb~@!^5v% zzmC2>998w@;n8?JK7VY!Tt*f!!e_QeQSEJ`&v&2h?z(BQ(*ujJsYJOL{rdAq*sjFf z4IjkokTO)Wx&WYD>h%6ik8X*x*j2jdxXVcR!JQ;@y?gY?xr=`OM6{p2PDw6eG|Sc) z3e~d{0*I?O9E30k+7+=$f)Rq{qKD4lwtZ=pg^R-RK?@my@qa(a**VvMgW54co?+Q6 zW^Z^pDzl?MXd`0t=mRcjxD4h*o;i>gqMScM(=sbMp|N=OHE#vk^AZ zBc&$%5+`d2C^1CR0K+UsETUuVOuoO$3}c|G8s0+S6`&=i-BvJrSg(L^Ry9XgK6s`Mi_8Bnyow`|z)w*B(v zNJQZF9g~D!w9$v5zdG4qc$Eba={puF8uWNulUOpxl2K0!TC7jj0Ys^6YQ-Cfq<%Mm zjt|SB>VZa)ir%eNaj1d~B+lf*+w4G;eX=%y2xdp!8h=F3dw{+TaOjYR!N%eVHcdnf zMoz<6wRjlWy2PBD2K@|4Wg5L555}92(mb-Rk&Yee2LHp@x!i$@aOmD-8y4TivCzAP zx49XbfT`c?38_VWzE>m=1LG-wqSYe2>wxGR^C)FN*d1}BYhc&c&StZG|2u_X-EN3) z-{kyeTYo`qb6pDsq5~RMH{7u(X+;q2nUm_+R8e4M?pUQr$w-+@yN-F%5wBsULRvDn z{j^}7|K0{)y&Zh<2oUyyRl3f2_aU~#rntHkl%g~>pRN)VF>U0LKIKG|xIWF><6f$k zJxsVIT4TKN>=KdO`@X>cQo8Y;hk$W{;m3eg&VPNfA?{<(0PN6@N~aD@x|aQ)zFaEC zD(TA*M)}@YH|ROLF&M2dZt^8LGAf9zXoxlk$rEAL)n)$Z)!nH(?LQqBv9QA;ate!R zT?#l0bc3eXx~#1T!>%qpG1Qq^LGS+9>(p}{DsA3fx^ihtA1jMYYN0mqVpsV!apKoQ zK7YDq_@?;{{JPNrE;W$US^VcU|Qs9$Te2~xokwuf}@abQ*)qYnhq#d65BL7lUbr!AbW&9WU*vMageSiBV zi7-%PRGp*P)A&=MVcI|LXB4c?7>!KsMI<^YYui9_AB#e1pFj?JM#YDtm>G?a`UO#9 zowO{f%&&NZjss*56h}+w6Ub%AOqaECNrv^n^*MC>bvdO|j9H}98d&CtF3c!4Kj}2llf|w}T5>*Ad z9Ey?$aagW(-0zQu@e2C{Ghy~C%yr>XRQ0?m{@?)KgGscr{H{;N#RVF2U z(6+k>SmdjU+bn*lc&{X3fK>WxqHIBm`~?HE%&kOshwK$ z)e_Eld>9WNu)%}m@RCs(yN3u6n2{01dYU>>w-TWfA|QziK;sCkg(U@odN>5amRaFQ zckrcbR}YtTHD=hFkmz8H8-IJ>!`ngQy%Rj9O?#2kPwZOf- z_2}S(ubg-aZ_iFU2m>q-w9C2~tpJ+=65e)OW?o54Oy~$9-$Ihh_;?fF!ES)U4_TFZ zyxsRCtjOtp6jkVj!+$`!x(sB?DDwHK#<0tlM7Kf9}7cm z&p)H2oVC}sidLMO7wz>HZYZ=kIuh1~3h^p-%wScMv;!SlY*watii!~N>*`DlRofG}UPe;Sbrk>WE+(%UJVS>$!?y|g@khcXJq^%>t!VCGLrBU7R;9@m@myEN$}gej07J( zSd3bwD2Yj#fO-VQAiM$Szz(w8rnp)yi;Ejih>la|7$a3)GKqPy9UZ4)^?(O|V4jZ4 z^mCKznRtS-p$A(u5UajkexUSwwh~&>Py7;(#DB{|T$E|gi%KNxZT_oP(FU6TBG>e$ zrM}*mvKdi}p1F~NUB5(M2Rk&2U}L5c@cu2eqamx5{PP!R=LZr(>}AD46djv{l>S94 zN>nwVqPRI3pJvTTIh>qk6Xq}6ra7VrZXzZGBp0jM0-6=gmj{z+HJm)nL?22>*t=@bEo)Co{HHo) z6oUQf0)xTvJD#%4g|FZ5%37{P6R$ti?)!_A;896{b40X~Ha>yc$OkPTS_v&oYb2<`@kn|~9j z7HF|&J(>g z7pqM%43Lo?dBqkm1dQ6AV~aGRn9v% zIl4YB?y?Dnwt33w(!dZQkaUDM{(p@ubc2N+VH6!%=tdO!fxu3}Z?H$Tyro)Rt><}A z9Fz~}QM2%&?%OfiscU*}@rKbIHO$$Pbl5dpXNw1mgXM#z>Sq0POlTm+jTq($?@0xF=Y(+Ml97l0&47S`|D zAXyY?6C{wF?G}qHFwa7&&?%QpaHt7jad(dwMUILa48TKUu^Cn%f}%(dr#LWp1l#)n zC85pOWx!2%3@b=zvn5JsV}FGSZMMY;?cFivJl8J$VRwl<+K5}gia*+E3m@y6@xW}9 zzw=0xkUr*4>rDHtdocj~890@cnSk~Fyrz=OeurHt$&r3?IA)G`1Wr8($ZFVbeArKd z+u~_Gtzmyv?IjR3^(ml%37ch0RciKhJzb+@hG)x@^$;Jk!yl(a)_-91Wksp(K<)wE zgCRo8Y)-MCcC4A`Fh4mW7gRM66`C1xvxJSydt56$uWsw9a1;DM>;n-e?%ssoi9{>H z<2IG2x)9r>b$^We07+rrU*Eog+1Ugb#@~xH6$bbNNv{G!-6(e=1~))l9!GDY zGEQDJ@)wpo!kXy)4B!DI((TV88${R6J>M|GfWUHw*55{qaz`3 z)^qv=!^M_t&3|TWo}EnCBX-1oIAtpzK=9-&&Dt&%>jIF7*8tG|E0=S?v&0k4C_a*m zBJJZkneK9K zf4{XFXn#*yr-4>9u!+W|n>Da~ZVd}fSnH!Ha(m63TgQ6gHMnvD(VOitts;?rLVg>} zUD&SvDp1ud|3(sDwMgNxw$jhv3Uu<*51Tfir)rT*6j(4+m7m>F$ zEF(bXEN?q2pRm0UAz;aqJe6XHS`!kD@IBzLI)D1buMT~XOjWZ;3=#fnWOQda1Af1m z{!$St0&DA4a~4>81s}M!HpkH)K!M>~-TId7-fEpo@>1s9Gn@nTf23B0vmrS^;~Y?P8q_0pu-D8 zhkxtT%DV0Zl2A;oUcPas$Swp!+~ZM@A-qrStI=C@<xWsi?so-rwMxQ%S{bpUCq5IPBURAB7eMawQd)`0i#Pgdq{W(c%z%}DmMvKMI^|_ z>TA7x8`fU0vEH>8MLk>YDpfi7ic#iIfAGa-gJ< zJH8y$E4OqQS)96_fLI<+%I4VA97j>=U5;;~1Jp1?ED~~Uo*YEa$U}{Zf5&VB|D)XN z;b@Y$MF()X!iN@mNP(32gpG@yy?+^)9#Hc@G7#1JV9bslKK}9OyYX0t1@l2T48eke zfTi56xU;9Su7ZHxx^@R~B4T3AswP$&KYID<=d;i6&ptkT`M};g-1TIGiImaTqoto# zY6at=*qV83kBu=00)X*+xgPSTLUVtO7SuQT^9Db!573dCbT*W$KW_v|oqq}3*rRq9 zFfZ_@)-tOE5oaw^pIu&5j60o-Rrs!>jcloGW-C)lB3&OpxDQN9c-f|`*Z~hYF~j>U zAOoYfi*`6Njkn{#z>_VPL!dKVzBhoP=N~5Gig$uUzi}>_UG5im=$X4I{*|-+tjn#l zVDs(P*FJ4SoREMq z4>4c4WWKQWGV_=$lyKEr55bzO9!{pUmT&BjC=Py{r^JP$qNzBrXM^kvyOq z5cR!>kS2cNJ1_M9#ok(TL2JE~@|^aqWUo!JgXw!LigjvU&+wi`&AWpW;TAu7KsVTj z*KBVhbv&E4&Y>_|KYuRekQF=ysbwOdlvJN9AO)T{_~4-M7RGxG!e5?VTpN~<`-;ewnv9@zC;j-`ViJ#V|N=+NyA&4W5?97=#yD zKzK=kzGJkktFAbZi@dqJ(_c6ETeXJ2$%Vr593G*GRqOXdm5T zoJ;i!*+QBY(g1Re^$_GGiVsRDq$GlY=hE>}@sTVyreA8%R(p9P_YCi(dL%u1RRG>v zyBW%hM!D3)H9GxQ<*R(QkPYnbdkHW$6;4PCImi;jG}CuP%%Py?#>f+dwp7AYYsTdb z*?M1@dK9BYaDPjB9D+8F=CYe$dDZ!z7cz+Uw3BlSoA)vP4>Ok#|kXiM# znoRqH{?25dc#8|(Pmfg|M0avcyawD}B+S$A@Qt#U_-MmEQcj7OCnSjV8X znpSk5Ny5V4I5N!TLj;F34xjXd3L&cW z(Ko`J)afmmW(yzu z*esUu@n9^n7Y(0f%UsrbbeHGw7~rzM;eoev$MdMwna}XMv8yasr@tfY*#K>9H^yZ| zpRfbYLWS0TdJabLVHQ9@mm-^HX`ijl$kXk}3p7U}fHT-{&mroVUtys1&FoO;+r<4j z_4!S8M#9!QL>7>`<~ zXAxle`fJX^uc82h@oH@8O3`yZqgdECH|5*NmvVEdSwJvt3EL1%uKPD;cUy~uaKbr? z)QW;lgj_L+A^ZLP?=Czs*U9P)<3R+tU4rKlR7V?9VRj~*T!9f>J}%E7H(CiBn$s`_ zuWrq3+J{T8a;)t*sbHD-AaE-OK^Z~W6YoNo&ELnsWuQzsc7Q-%W{ThA`<;q!Iud)^-$&!Dn)!V}#Mm_N~1%mC@QU>(Y-T6cQmR|AZ^t zdBcT_X+=AJS>J?r<)}Ms!#G;#XOpr159%v0cRLJ;;@RK%n zCzNOJ?-+zoHv0y<_J(8#QlxWr6QblHK^!W1KV@t$|NY@B-hfUFG5Ee&;x*(>VI(3p zk;7yNVZI*@w}~V%68iO^7sEcEYI^imj!;io7XeA$KPk>Q(%9o}ICk~SAY5Nof*f!+ zHpHiyWULO35926}Q=lF17ITbSwBY>y?H|57%=YS)$-;+zwYsnU630W~K*SH@k$1>^ z+uDBzm-1auiF-Rco4ywHNvwd0_RG3zG$xfNNAPN6O*)^707kzSj{oU@v^J`%UoCr<{@1_Uih>%a|ORRphj5M>3?{^Pw zsy+W|(9fmo5DClcL&DjK%p!x&4_1C)@{nN|&Mv@5C@6lQ-it1|LtwLkxW15^<1TBe`eO8t4beRfBPNM_rw6Zbm#{^AhBuUf z;Zm7F3NSGl|B^iUr~gcre6B(=Mi~?osO)yZ2kDrZyJm2?+?94#Bmet_l|R4yqO6b} zwu0o0Txo@@?~|;eD9wJ9-{<{nRbv~`RF0Jix2!O_~+KT9ADk} zWK)oSg{Q_gY=98Y5unvE>+gA2<_Ij45(_f|G@Ln7{n5%IgIpQjQyqPbApLejI;QPf zt+h1&+|S2(ze>qe;J4g8!V@;3Mfh^#ff&B~2S^!msFhW@`@j3!dfj(#2sU9f*xeDD zp=I)hx5NBgCPa|#>+Y;wqmU*9lo|0eRd2B{snvw~kuekEMYkoLhIjq!PqL#m#yvM0 z>6P~HqVq9vr`7#yIfUXn_SNjj@f=JQ_gFC*L`Nt^zb1%dVJ^t*U{I*}1&&0N0k=|( zZPBnu48}^Cttq@;wx?0>cML_nFBsVfF6zUPCDa@FO;1yk?9)m$lh8f8oehZ3O`B^@ zcwN6mKm+BVVSSy}B{{!R&_sSQFi8J6f<{`W8jllUu+L{A#PSlrZJWvRkBtDCP0zf9 z^)O$IQ14WO)UN0mXkAZ*`<(DQ0D`~7EVKXqgayrHejTlSa<`9Iak{qt{1s2a*<3KQ zTY2t*(nu`i&(+er+oAvpJ;#DD@gXEDllH-)^j^yqkj8@0rA8bp9L(IzA}hFkG0qoH zSUH`B?;f`*f_Q&Bues`-WdLY9VZ($q{#+&& zBXi2%KPk?F3<7Un#~(Uifrtg_qAk)tAmFwm+DlvOuzf+`KGnj|g{!IB8cI~d%_NG^ z`M@%bgJ-#$v;%uugzax*sZ8sYpg)UutmVm}RIB*jV}K@vO5k{|OgkI+Y; zUytBeC|z>nY!KL7KbtaVL?&f4M3+j_+@5|;jqCVQAAkIpJu-dce|oivUDx!nlH&W? zOsce$1@=G>9JNm|L?6mYD)Ci>d5jn8n(Xy9^bM1W!sjf%(Gc`=t4j;AN_DFWo$GCa ze3zk0<+5$Mpo6DNx0@;56K~^>;!er?tvwbAzOMH@_?GcqAS>eGzu^s_*4xwBTKQwy zJ$bG>WdL|VG&E6BlUWEA?5!Fx;ro->v)->cz!XH!pwkfIHcW(5iTnv9O`NJScYxAZ zDS~$MJ(>@C`8|BwANy#rmUk(q`NzY)A=!1J3wt=3c(j$R+HhaSrCR?-svE=DFHdjpw+1(Uuf1PGcedk4S$+#rWoe==hn$5GbYmb*t!6PDkp;LCHojSk~~*N@@F*RKB1K-;M4l zY^fM~HEOc9M6RoQpsI9hDb_+E4B;{iupB#$3P`a%$>+q4ACzKZtqZ3Zuj>+lGIbV5 zplElwKWrFQPtnY_6_tIl|Z)HDNzot&--Ebb~@ z|Ac0);uMHRZi9+zVepAqdK!@_!&WW{G1x$V->F}%L1ocnj0xK}gIMv5~x<>gXhe0@uBS859bs*&8CZkyeLeEM!Z0dP7 zIbfkc)OqKmB`(LV7+Jri{#vo1wl~HYrxdXfcY40&ZQl@NgL$uXMC`buVVm?+LSxi3 z4Q_H0dZx+$W^4KH-Arew%FM8j<_*2?@`OM+VR5o3RG`E5O7p7Nr`lB%Fq?ef4jO7` z9Knvx#OCf?#(4ipKQyMYqQL4JlOdm^j|FBPn)D#CF2JNu-C3e{rJ(Yt(xrbfFsh8G zk5?)pFs6+)LC82$9sa|iga(8T-3Jr`nkdv}T)(*`y469$hCVJ@3EzXTbkU`G;4%GY z3Dha2ZzhX!0Q-SLx=VuqKw0p;bbx_M73iPNT#KaD(BL&+gW{OgvqskDMHK z!4SN`%$U zt~kF9^;0q5q;c*7=7G<{zqhIve6EADHpb*u467tIOK)zW8r6+zpoInPmRe>xwSiC8 zqcW0r0wuPnYdI=3i)Zjpg)5j;CE9G_GSA)fTzAx;ocYOGyx+OjN9z|v`gWmD`1n{A z=Z{g_`k&-bUkS@^Bid@;Uw<$y=S6}Nc;66G@)Gek*!rEV`X}zYu!#uI;w_x9*iHw| zs;h3iRTD~j@)}Q@fZyM1sb0&Qg}kZu7WaL!ZesU%G(a@EiW)mR_oT9q+7`0PD)Ss{ zuL1zhhp5)jfXK{DFl=5fJ;xLbyB}G6(z`Zb)nV6-lvQV{&M72L=*F@mT6gKC z2q<%0)`kSW0Kfx1$ll9MZ_2(Lo@ZU;{C+UMc-`GZkuDy<(6k%$!Nkq-*VH-|EMf|y zl3iZj8RfejQh<%KkzIVbv;+1o5Z2_x$(!Q%#thRdOPnI!_k>`Smm}g5U2@SS@0^J~ z&F@#B@m@jiQMCz%rPmpjN+0B*BkA;TXlA=*hNnH6Qpb-ADFU+=r0;jm`5;JOI|_A# zo{h&Qo68#T zpcl5(X(EX7gFc)jVH-smi3=6@9Xrl3NM`&+)%2?!OOk!$%5hXpH9>UiN58lkX!HsM z9UqA8O2e8l!5>mHUPxZFDhxZ&SEr=25Tv;ad?jAs?aomQTj=C>$oK~8wq%AjHU-q# z9OOgia``l-9X4@Ai!hsgG=(8T6K0F=E{n1k6aiaz+=9^Qq@IfIoj_t?-av+@Y}*Q! zry7H;)r!yZ1|!v2V_l*&xY+0Ig-O??Gwt1+J3m(>d&2J{8;65)rYmpP--b>}+KT*A ztNzNs-5_>7nxup&Z(rkeQh8ysxUlO?T!NCK!Yg$oZMAVhjs0kcV~5ET?n}-jO}Kna ze)5yHqUvKpvVLB6s*<9ySEO%ORL?&(K3Fz(cBE{ntH7qpM)QkMo=q(^wWeVhd2Woi z7QNgS4q~N6mp0vs%?cfYOVz!K753(6#8(bwPZiPu_kU0t^k9W#Ek@0 zy6tiUIs;^ph$h))K$9TW_sh4+h9CU5FVPigVlvv&4<(&=i9Eq~*s(mmP$g-TK@Vv) zp1Q;=^@urK*=F}@By!x{d8gTrPS5?i+VJNMDnnd)Hmre`VCI2_?G=tj4d4FJ5_R!DRD#+N4q3bPMg&IZ+_NG zlVrmtK8o*U#GXl9mzmUhbPiu}I!Yq|XWi~oJCEY8K0p?lWr#{|x`u5-C|7T@m`PJY zq6zzsTf=>OhWmw`PS&YuPoBPtudZm8h|AUJ8Chw4d*T;XcT|qRwZTfK-u;o1L0eSx zJ=LV;DUqoXXo=MtK#*ZywyH8=AnbA z0OAT_dZLs$ZY)tv?w0s0$%&<{@@zISvE(@A3GH13!L1Mu$J&U#ebql^!eX}&i#84| z2g|LA)n37B!A9J!**CDg+Rp$CE)m`q#sJ8yM>epKuAwi40F zmLm0fH;V7^>z{H^o7tj~-Q`v0fW*57=RB&AP}YDOy=ePv-r4<#yJMR}Je`y6X_Il4 zHdk|IhZfZK7Au~s_GL6+iLGX5jkCC^p7*@5{41zIuqB$>mJaTdiecL?;D`wiKhv#d zpD?~=nHe8+Dj;fJf)hlaIbv(=Ns+1EuzfoU3ie%txjGlc-FPFf=ALw_Y=CYy>VQxF zp16{ROf+kSKY1OK`RTdP&CLn_Or7^cvmd4#Vl7>>YN7a3As_}23{6OJ#xVkUt0&>{ z6ZzuS1#15nD;S$b>jp1LAi-nfV#o*{jRF#*YB0+LZ(89Ceb|?D% z7jXrp2#iKvntqleO?X{vFHuGCE!1AVkt^@ePVo~`dAx1yPBbY(Zd}zw{*j1fQMB^t zHTn*N=N+49$IlV{2p#O;_L@@?1!t9L2kgtWB_ugq5`_U+aruSE?~5E8hE(`oWcg?~ zd{(DHZte?)b9*zeT?85ILqr=8AtX26Zg#y&Ve@9j;qs))lu?i;Tps#3N9nnc)H--K z;i6hALYFUCI>1z3F)1-%#i4_7%;p!K7ltVum^4De`KGWpHL)`tFIJ1$wpfsvXSHxP zYi!!OaN`b4UsKS-shNdttOm-kF@m2MIFKvC^|(>j_lLFIx@fe{{q`0jf{{j5NNuFD zs_Wj9#L+#}{Ji&T6-&GR7o2PM3a59L&i9e|n%btYz2H)9U7{nFAtv42{M3^qn#1$M zP{OTSp3g}4CG|gSszRU*6@Loe^r2gJohUEy0og9_jzdXp%F4{}!0ODR`j7>TpM@Ws zT6(YH`RPdv{Vc=Wr!rul-1BachF0t4NuNBDIB&;!}W2Mr5Vjr^c+EaD;0J=ND?Z zDLB)i4bYKbv^Rn+(0<`-M(` z&wklB6F;S36>*(KEA~8WJPf%La%far(}D-M=d&U?Mb7MmacqKu^JzWS91I4b|MI`oY8wQQT86F7~Dqb)w*Xj&lAT=7}$3B!MXeb!cbLE)m*Dh{Pe;|4gk6u1Z&Dco#K^6aXbSTKr! zkxmpE6AU)~ALd2J^dgecD#xXkK@DWicx?A?Pvd+GV+FHdQH z+)LzXdy}kH%+B*@h)zyWch5hkIeiOG$IzF zY2Z~j@i$hfqVzGM$DZTW<;>}5)Kvq(c1bvC|L|))|HLF}ZNWaMHy)#yz5q(UYJQwy z6q9l?*&Xzlm7qQYD7q#HsqUZd8|O{ssclRT)JO}||DH__5*n92l=fJxv1;qh9V(*4 z@Xr^yv>+Hlu{T$#=Y;FntK7E-A>X{~P(qoI7{InCn&z>CM8S}_$0Qo7avJb}x%)0c z@^q*CnLvGjyy;b5uCY4}!{}@bLH;q;*}G9i`Eu5@EIncf^{F0DEC)NnOfS^1DP??_ zLIuI?zXYorGsF$T6(w&V-NxcOp{kkfezDl@luTlGZenfhKl2bV7}WYJ79J_gqW&Aw znNJ(Fl*>2a#oUx=(f4~lF~3&eKRi@Pa$SCeBmU*-Y_V>HQ@|fkQ5-5GxU};OhbruU z@{rhKz6acCYRy7H7yTr*Gqr|nnrcU6Gr>_DA@t+>D1rr0kS#Au=#(8!Y=3Nj8t}|O zy|#U zo>kOYT3ZaGdJJcV*HZb;ZNH9KJzw{*Vu;R z;DuF#TKM%4h!W0$NslKlj0PaGN1rbJJBxc&ApWWC%qqg*j~^R|4K7!#|M-%3Q>&%Q zaCpUYR6W@B8c;o^_Sv=pbaHPNQ|LS%=Nh{*_Zq$3nOEhckzgr23wxsBU(GIeGoXd1 zk=YW?iW*OicjrwF2t^6&8)59n6mo8KrKg2Yq;>{jRhC-Q*c-kmUSH#xDQ9j% zc(UmaxFIJ!Z~_65fx{Vt9XHGgDZ-O9g1u*+Vw(O+Qi6b1(luZJg9zc^lXvytCWUxK z7OLY15q)K2f0n)mMnhw!yV)HA!=;UHaYNwGw-{J7+;amQ+NH#W8AoD@^*pL(THe;_|Y{|B!?T|D8`9|(!nCDSn}_C5;b6@ z+(fq#mt%eIMlAKh_Zs|uU1UHTf(7QdmCw1iQLkdgDDdo=f2p;%BndLgwB{WPwbUC9 zw)~uXu~tT|nmO!Qe4#{Eoi__6xd|6Bhm_#rLXoO>O?NnN++fR-4POG?z(&HJi!qfH zYBH$rjqU?*WLP+HX&=w`Rz;hyC#PorCj`4`*OsBEC!@A!dcpw)_sd0$U79*!O3`P8 zU?&i>Bo+)$&ACECGD+T@cj_i!?1}e8k}y~5k8W7y8m0Z-jL7J za!)Na?PPaUJkqY%f}cY_fOqE&NrXI1Q>tgG0}(gHsMZ+~TOqt307Pc#w>>lcw@WyQ zgYH0!!x>Uik<}C(=_qS(BZY2aFhgC=(voF^IBh;@LvyF#qcG1^ZP7Ca!FLao`?U42 z)6@WX#JKwu8#~2f@*XbaQvaA0Kz5bHOTL_7MZQayQQ& zM2JK?pT}8sGIqFs<~SyvUx;t=;T$>p4U`TtP^&c>oCqg`#=X!v-Uf{*g}JUvbHkeK zaOI&g%J$K51tz4oi2yzSuaJ1SHI$~fERS;$blGq}y?_T)Z0jB-tZHJL!VQ>iSVrzVL$A3GjYI+rieuz zlzYywf-%qqlrHLY4cWcilSjD8foez_kto`=ZuY@ z8psDn{87_mJZ8W8-Kkkk8a`AWj(2lRddVq1z}kjclACPcc^opqM18;v+h3VfJjiQR z9az?TFxDSwZ+(`kf-lm+d$7nNf8zG(f{Ikde!@VC_Qa91;qyr<1w6{|I{|xU?(Si9 zw6a|6sI#ile8E`G;hSw_b{mOve`*x0b#2DyE1II!Rf*8HD-iiehGUE;qVdBd`LLOony> z5Xs3)h3LBigB7exna*pEucJmFAp$Khay}yCg5!81D@dD55(0lsLMU@tG!5g$rcZa1-_bbQ*h9 zS3H;LL$bbKmx|N-xmIcXrUuWhL=?GYYj0Ay-h#PS zTpMt;@GcWAKp*kN9S4X82-c=^teDm;UhAu0JxzVDtLF+ZPY_QQI!wfviyofDP-GV54Ti5wS7UEZ1m;&BBC}mN9Ts zIJyVHRmg5r@M-D{^y;M#F~?Da92oK!$Wsq&Mp@=GdVrxtTLMaTK@!8RBCd+IVcaJL z>^+m!>y5}sj?L%A6zOdUtYZAqC9Z($=J0bZSKmLUHhk))w3nnlfyyAGuE~6A#pPP30s77dg*Im;Q6Zgkq2Vb4g+i8u8F$erV@}X`C zcm0pF(Mqly?jQ@++G_))vcp(~?&0P|JAHm1=i3i2vw%S#PbTD@G3Zze++$;37uGen zxJ4_Elz9)@oyreKmY6UUQ!uwH6MHt;;BmC=j+Ohnwz^!LRWh&ad$-;L=L&nyiT{w) z{Xk3l>XO}+WH z37BBQ>VSp}C@t&dN*VD5FYCS}0{(x-tm+eMMX#c;%m&g9>b6q-L`~DXF;2)meWg+I z91uwz0lph`m+!N-$<1?081v2j{V(tHb}#QC=QeM)H;xAZ=Nld>0pElknfW3__GwVc zgGHeUuD{aw3sJaHC!{v(nyaUqm(rd!XH+fV6S#ibOq2YCLyVo)5BRe;bgEwIdNYE) z#;5r#j+wTdoLxX}zi^$A1tTMZssd6CegP6edf?MuF>c^$Y9vRkAN%NsGO+c_5VoYsB zG4MVbiY)D4s$S^JHg1Yct_q8xq!w3MI68+QEb}RgPyfC+(oz5ILOO4iCla^ao3oQy z*i=VrXuKwaLbFLqITb~c;j}okZldQ%;Dloukl!RHUJ$`{#XvVj8Z+XTFZ7)l8Jpgu zBJ9Az$mqdWo8pOf_|L_{6ES5!W>!T$0r()RmNVdGVb>?DKQ$AyZ#W6+lu@l2q;uEysa?p3pk2%P-0T;;ntto=_`1vjmh z#}V-mT}^10s92x=MP(`hTjZQsu)Lgl_uPHGIA9YFhLOsAN6atjgIcSf*7OgDmFEM+ zxiDAbAkWI(Q=pFdrN6cAJ)Bb#ETCIDjb14Y!d9mtbSd~_ksa6a1#TEu;&a<^DquL% zs#3Dag&$5lR@kxIw${ByGBKqlonLg0j=w6JeDYrFM2zG_n>Agy?VMvawy{;Tr-PM^ z=IP!qHo+G}GH!UgZW|#p;!_zFe9gPdrbBDnnK%IEQhhS!qe<;8_6H*+Hqg`)?e5vu zI1d$Z>>m>DmQPC@KRN=6hfi$`o+iOCZY+6wKN)@CC=?ruuX`MxOsEGF4Z$Gp9mqV{MSj9C#=2B?6itdF@o>n_kkLUkYopV8zEq3|WpB3FYU84wRUBNu=9Z=}LY(v(&s&ZMv zLs0&i`PA8BK0A^@G9URTtVQW$TJhvc?|Z{v+DQSn{U&i6SD@~`XO8BeB`v}^0I%r6 z+M)Q7x|@Ete4w1C`z7P?R!@Dg0*lg@M@BHlthQ0C{u8eaV!Ig=c}#RDvUZL9qMfWe zLP7JgpFQ$dnrXJgUm(p*SB&!RaxC6SfN_*LKj_$EbYngF(al4lj}z5Gi}s}K05kR0 zVVJ5DlgQd(q&3=nH{ZAGWRv$<2;06b@MjB)(CDZ}h}ABbf7zjl{Rskyj!q5FIPQ*9 z#^KK_Pv>V-H}5E1zgo@;w2bRh2kSdToB>ome6H!Ac0W5!eF2SQ82!f%1|BQy}6B+*c zt-G&lhcW*83O*_J{OLSwa+h(6`+0E8BEbwjW7@d8+vV5Q*Oo`<>eug>JAFcmKnHWp ztglyZrb%{>6>fwO7>z~WBL4nEJa1@t9{Lm@qXWYN@FObW#nK*x9LNeFQ%IPv;@|JXgnTJ=@^%0gKPF=(-u$TCe z!cCsRIb3}uyq)C70cC!%fKPNT3v_1r?FT}m&T$uIjS5rrH(BziXfrPtT{L#gIv~AcvNb-+k$-mXi*x9Iyg9?#iqeY;Go;y!>zqW=R{~Ej9VYj+q zH(VqOQd*qETd=lg%`iyy0m6S)Km2J?YPUO3B4{kGoi;ox8nw(-M28LyR4W9FaVP^c>C?0jx10nuSuwMz`~;&xD_XwP z(Pgl6)Zcd%vmt-xEw#Yl)O-ZCFeu(a$@&Q7d0R}g+wPLq^Oyiie^WKMgCtA3lb7z- z)4dqk2pp2y9Nv9M#cqS2L{u`O6RLGKt&@{4mwH16Dqzr->r?gflv&RdD;YiTX7EB~ z`JsV5OwR;#2zwsl8E|{OL%ocj8f8sE>mw6EzMC;%Fi(LiGxrE8f`6+d!6x9-1Wn(J zcijFGSU8;?e<-%fOzBfe zU0M`AROhy@Nq9NXvwu6VD%RW>5DX;uz&ep>8)oxOfu9Ja;h`Oz~WS9@nCKoW%) zYKTcO3Pd4}AWHDZ#ZxJZ`I+58`qZXsK)f$rn=h-yWsyTtg@>Wf{(O;UUZx)X-H)lR za%CP)sykrzld}0g5VOgi@{$7@vB#)+aW|sT?^*_Vs*fi4_$p^a3rni@AVC#cDa2u5 z`&H$VJ3>7ob9FmDfUYq93{@5|8ef+p8^pxzO;s~(9aovL?og}9l zV>^9;y6r5Ww|6cenau6e*n?lNBOv>bUF zn~*e{dm3YhkF=hW_*Z!beui|RCdLCa+{64SwAEju{wo-jEv<&uLtbJ*kwcdfOcQ#w zB!9O*{rC5dO9@+>mXz4@_$Q0MG|id4_z~_#`q&7ic&lcLu}G~(I2yVH(yE^hWoTy4 zpiv$}W4y`nUy7dSAh3zwE`TLW3Myqw@{{_MmL50$Ked}8t~X|CpQ;}+zh`g&k01Td zD*P?_)3xyorM3L|uplcMC17;R7}-aJU?i;oZHLe~ewmr57m=#AUCeXX(Efc=9gcR& zqG_OW6d6C3m$E#3JU!ASd*J=xWHj|%~2c68q5%V&D~p7B|7-uwUhw`&@{%aCB1G=CJQg87SZ zQ#rbk&IHzgc(+YrZP$^(y)GLV^g>g@8YZI4A^3oECT$qGko=s*Jmx$8A+-m^JRh7j zjt$Fy|Ev_F6#k$8y;8F>F_D@(RD%mf$6ej3vCds?FaT=0?3$us6yyW+9tgTa8lyh{ z<*QbBL~l_WP3I+Hu!Vn`rS)^ewN@%+UGkP%`)nc`;Y+8xN@v{~g>}ZYC%`v1LC7r7 z={0(66k)JR)jLF&rD0BfCG-FPLsQBdP{j z7g{N;RYnCI720!F#^|P7ZDA168>uS=<15$*!nNe)Eya^B$35VQ6t&vF@Xvw{KTo1W z31Z0YADEdMLo$c72=ioBapQ>4tY0U`vMW+`#bj$maz>Veqc;FpwXtxPgh-2OM-9QM z{~BBTT*Q^`aIENK|6^U8ptWNikUTlN=U~%o7cAH9jXvJqi8>_o;!T`Mv$uDBEP>(% z8>u?8?cX|LP&$r)gh9y6fKEhtom6!pDNwE;KQtx%2cT}lssKKF<~XZVUfBtSMT3=q zIePtx@c74sK@wz`*AVXZ(066Ygh(l;=v{sYN%6UudyQR&rk0ptR-0|iv59?fH@TeM zwSIX&VBE2Z8*Mdn5Fg z;osQ+mp{PRpEVpeVVL!fP4rd%#3U`2OO2Xu2d`52giY6Z*`qMdlB&o|| zR`yzd>X^MXOnoi(mwd*GEpGIn`87(Py$Kh(Mj}&%-U~;oe@o2CD-GMI*$A)LiNLoC z)#3Gaml~Cwtt!s#dK)>H){{{Jm*rC9hiS|j1%;D$ig}H+FK6@bHaW}$ll_GKiStLx z&PU+F-;HWI_faSNL2o(E9`EpuSe1YErq;d6ZLYA)$C;_P%{n5u^|`D?y#Gu9wYMOy zxMDezi96v?v$jinp5w@>64RX^mP0?&jNtveyKUrZtA+xm7Hd;`%7Hl>HJ^~r(=Zsf zL4uQqJNav`OfP*}qqDUfsWALn>Y zssqbY8(quciK)EYh*7b0l1G3uc49_@BY1S*)acm3D8nYCb} zTodc1x$Sg+>70PgUgsOC6-C*nX~&m=9+Inz_{opjg&S;;Vn~B5!le5HR`E7Ez#34a zkjk2>iOH^U(@vtaf3n zc33+eXFcQjPl7fzC%jn0+r5(;xC60DvflV5%TNVWh+B;VZRZKv@X(AI|Pwx zK0E%?#-6T3jL(`ce!jVS!}A8>0`V&Egmso@mkeJgefOv{U*oYuIX52=r8 z&+mUYcU51)g9{5nl!Yll-40WTys{)}$GpL`rjsh`o8A9Pskk*4BywYV!T_1=7Dz@K z0#p!Fe7rKphZew3yPOwTzIR5nnET9})Xy~L{B4Epw4!;}HGs*N33ms$WjgQ1zv|rW zDzciDtA`625OepcA*3Zxf3N!QVQI6Qk9~R=e9p+4#!XKe+3vqs0EV88L(!isnu&M_ zVMNcFB&5e?ucN-sji>9~KENS&M#iZ@3}Yor^6~#PzVG5s72{?1=fVBIQMO(ME(Mh} za~JQtYM^<1fyi`70~2PgAO0DVuYt_9y8s!&b+8%<55%YnUGPMft&-mC$I?`yb?)0nXja>un!L z2WVh*Zj+TdB=soI6sOvchBjX%gUzRoPpTz(-_b-c8?IqZ@m{M{Ibn(;**DQ|L-D|` z+jg4%@W|)a)OcTf!+89Eb`F=BLtHP6Abw`hnw^W(`J-2q1%v%1 z>;8v@F@``ph%Z?@CYL4;aEe$n=}IC(TK zA4Z%&_GZgG;V!Px>K{vFVDUpzaVKdl5%7Oa0W;$_wPx4|fqc<8Q~cVybp{@t$U@Hn z%Xq52tTjX<>D+Alo>M`ntqou_=+M7#k~&^nOI1P&UGhxTi__{hA0p->9<(zW2mj0E zHct|>^C~Y5D_Rh~*@d1KH{LTj!KKDodZ&-6k+AE71WL>cn;gBn?GkHB{J)s{{wNbkK#UC~+#W2T#%C-ZK8tK-6XIYc#R(ESRB}J{YpmD9JnB`KjONFemAL#UDNlMr<1Kbwvh& z78!8%h!`9^w9Z|t!W3a2weHPb2LF~5n8A2F&$)1b`ER2}cL>=&)kzUwvsL z)6NmP{T-oDwd~$F4BR#qn59+bgfAZX?7p}|p2|Z{{>%~ttM z#N_35)muZHhN6wPX=%_E7IRg;t?!+eJ?)*NeRSy_vT7jfX+e4Uo|tuCP9L&dZ{>oXXS))P5X1>Y z%ZX04Kn8!V{(g*0%)c)Z?pC0T%ADS#(Xt6L2Bjbxrt4}Ka`5D$c}&Z|EX2;%eU9?1 z-y}i|`YcoMQTW>NdBFxYV|c^}9;QkI2OI-d^6RDzzsWyGtvzBGC&Mq0^^E&wJFT1k zG8`Ykm$!@;U@C%iyl#|SjZ_w!JZL*B{e8MNBX8K;`h9nS&B4B&hK~zH&{z0bh8@-x zcG~U0FzM;ez*k#tg8;e-YLhn@8{<2xqrsqp!$qe>lq%FkTulfhY_@&M=0UoKg6f|N zNz8s1uMG9t8joxg^GC*+ZhWdMS(A?AB+o^X9=;1^65rXoIQh z(q0xzkK=BWBOIchRFqAK@A8zzaZuNtUjwN^+%X`ircwuiNKyva6WMv6lmUcc4P|=ztpbyByn4RGwxu zT++tJnMO~JVUd~-r=a(})8+B3Ci|jxHMLJ94?FaOgGB*eh?!lGnQdU$_nG`qc571w zb4?Z{Z+S-Msh_4@!=uQgrIn}PDBFctziaUy$?8=z{xtv%%{5w&^2XZVo}RDBOvml3 z6oW?sjR2Co()AQrsp}=)cO+1)j8C$>oCZf-J*b0^wB5e20?G^(|HaM4l-Nl|kM!;G zeR}aZfCD*rIb=B>*{&G=UzN2ZT^T2e^J^ajE5@wsem=qSeM$a@_p6o_n%U_MJLS z_!7Irum*%fW$(m7*_O=c@~g@f!7jmB+Ya*?OdcTMnMX#iNmuPRZ}oU~88(v$vm&6F z`n6Ow`z1Yl+j)KOjLghCp{=P8_S6wZZYRLHHtY~@DOc7P3F{#&Gff7Y#tq8jm;qRhFeGp=tLNde=?o%c*2tb&#bZdCC1*+-(r(Y zu$shz5Rn@l2|r)<$G(M3U@S3C?-u{7lJwk-+OYnW1D!YS%~ieXD>DK{W}m2&s%DU+ zl%*$}HaE+K4*Zd;4oukh+2#%WSb1_|BM0=q&!Pox#?@IMb6t!1e09Kup>)-69kxN; zb{l`?44tdfIHYoPC{yUPhWx;#&R8e*qqaMfnOI0$5Ic;d$LSt zH#TFn<}#kT$iYDiUR3{iz+d$;E$3RpVwYwJ=f9P^rAryt6Wo`x`3nrvgzpmqItIvk zI>57cxd`76d)Z|4dD7!ea=$e@gr#FhxO+`$X#ZqTfHUQv>VkWT7MQD7@c(Y(*XQam_;&sL06WT_ zU0Ez)_;F0N=HyT%X@!~(`%ayl1qHOJ;v);EiHKvAeZ0N7qydWX;Amxn{SK~5` z`>RDXey=r(`UOxKJ*gWk8=^QuXVe&qDP+8@0>lWtGY;NPNg}aHk0; zZ+cI0!G?e4;N5qg_(uynGmsgTjHMqLz+*4f`QuRzX_a2uR`4%zYZu= zyQRQCdQxY}c)8RjRn@#C&h)T9^;OPNDroZ1hG}i4h8tY9x*$|4Vw0t$*!*ia$&!f9 z6$*Htqg}PhP#$(Ltoo%nO7^Qug5|LPbq~}HEp5oPBFoXV#!e#@hXJ0t$)`Bz)i zKMTttM%uSdD)+nnBcsCTo2RfK-2q-{>J05uJwb%RwXYhk_vgh%ypOwqq-&$Qv-`55 z+jyj02&I5|jo>Q5m=$atU+araKKV`;c|4k*TRnIEQM=;xKkD`(!J0Yx#NcT_{udk*w)AO(R?Rd#?SVM5Ux?t6ywW!N2XW zPe(2IC3Ocr&h)p3YZ*>yV3Yb&?}1vmvL~hC!|DdT0x;Ft)oES)i&CXYmLQ`r8)WqQM|O_iE!JrvXK_Xb z_xPXu5U|-ZGt1hDm0n6ZXM$NHi(`{Sjl}dj(96(&Nov0AOevHm_+J3N3qkb7k6TC7 zYFBQaZkWI8P0O0qrv9#4w~mNx-G+W@o)hXLx2i_9nr{1l?)V*Wx4Q7n!Kq(wQqRLa z39=g-$f*}A!R^GZTx;&{_C_2-Mf}?>?L=T>s^DHDr(By^sB7xv&65wmQ#z?eRwI@F zEy>q^IrdAYS525GLRT1VLcwdGs^r%~RmsmnRqFf!(Ba~Bli%5qT5)ikt3DX5?gpTg5_L@Mg@*V*_6d{ z<`%_@x^4p(Hgo)9rHVW$#Ow6WsNUDC83ARo#?kHW4Zrl2TIpd*_e9$GNF{u!c##jr zCZm$8HrqM_5PZj0pDnInc>Cqk2>hfi=jWJ3>29)r^}HZoD!kGHdvjRkX%aZoYR-JG z{W4YiSai2@tJ19X+28|()IfhBjnHkCR~w%ltohcQUQKM8OTZKqbS{IbQrxw&`TF7U zRrTcZ`P^y;Tb0%?Ar(Vn1;kHG^%ok+iv^(eGQYeMils#J`TjD_3t_buu4m-2stlnZ zO88xWA64shz(L78L*_o!7XTD#C?DvQv0`Pd&IBqYd-`#gyKc)vv%+1gqUmM}p`UGt zi| z+cZB1L!{#55XGA>?os{ZVs-KOOf)D#iWCWd#h-yWemtA4@_2UHIF^kpnC6DIVW_Oa zC*(I|o073R#`dy{?T4$%KE6i#=YpQ7w<%gQ`E0Bf#O(w^r5$3n7XHobv&_-vr};)F zUe_a*EzNowvV3a6&qaD>+-ceVxKy5U#l^4%8T^A26&OLX`WY$SM>V8=x*3nHnw2Df zE-0Y_^5rin3PK2gMEV;^woC3cBGO&9{=SlbZ0kzesT6J`Ed2W zM0b`3C+9>Y0IZRM`mqy6J5_5vejjx z%d7h6)2oeL-`k&hsC2#ka?cH8V_?QHLIG+3{$jKKA=Jie=58&e zxAq&8FI!pWr1BJXaOIp~uf@v)Az!|%Ytjjt>k z1mBAKMAs5F@H0P*7v00WfZ=U_;ZE2pZ9Q6XK$wOunylDc&D1#7LO{b?G!G5(%^oxk zz#hM~WqSO$Q_V~n?Hjs^Qj#dt!g`%9=yyvcT9RwkA`*YiI*c)Gc%T#)B0RQA5{=pw zIcZbPwO-C*d>9<-5FkpFz`zi7)b@tKQJbgf{vY~qV8z(t!@c_qq!?gNZZr(FIx z7e%)CAl~IO`7Q*AL@`pwczfiv@7@|IEh(7@gVW}$Q`-ZrY zKhCK*xPwvlf;&56=S~oR-of{d`V?=8?dFK?AbF+6{^kC;!}X4CbdA9^(F~7aB0m^1 z#!~j4h+LFQEQuDhUmWb%+k+-2^-el=CrVJTp^t+=GZX<)1Rv#Znhzi7Y8^xU>-B;_ z9T1>A2SJ&yL?DH@zGjFisK|1qdAw@Gc?E-Sl&qOv@YJcErKdxGlv{oO_C>e(n1+31 zlTj5?I(`oZfp%Ca&^ae5eD+31&X^n5s}K9l7-gpsm1H#$=zz-- zC7C^Uh#3ppS%mr#2=g-~c1Ne^-@kpXj;uQI>f!q>H}^e%S%Ima1ZnU;iUP5|fq|DPA?PIOY=L4A=IYhT;RD0IzPa%q`CN7N0r~w|ypX}i z%53QgC+FUteKF~F`+MTT6U9u0siSNsP&cJmQ6uTQ5-S)ZXmbdr{zzQN7)*R6hsEL< z@KreK^<=<*=-x7i+f07R>7j~)c5jCNO}tUZ*X9m%RU3hO<)z!1itJ=<3GD^$XL1U= zaEjMAeBhvK7`F~z9sEBhYoPO-ds<7Y#3Ex|{d3ETG(BrP_}Sq@0#Jlfmq5+#G${kT zIJ?y>kxoUa_I1;z?=WvY_E&f(_A zzur+iLDhcfedDiHqPHh%ohnd7=nXZnjH$vScP3M-@>eXQtDv5IQHqpJ8RO+RIEm+H z;(fe?=G4!z{JhsXnkC(}e4QuSJXspkbo-vA4OkO7lDZ-Ag5}GO& zW!@d)iiQ1uWl0KLX7yDK4^^E&EaOxxdK_?nu0{?N@`rLv5B9B>G!;o2aQ&=18V>*1 z>2>bkTYge8(lN>4x_G(lm07kpiSzwOh-*chXlTBGlrV$9J@A`HM$fsVWfjeVl9fzx30ATYIm zwDqxF;9<}KhH0vuCCuWy%;qOOr1H>M(L?VEXN&A4Ui6D%0au=)TwL~3Q4SWke8=%( zQFEiP|Ns848#Mx3{`m2u#{&a~n4mbIo1tGhlJW%k z2OV^P_0`%&c+MUT+@YGGvqRjihray?D?{ioU*)UDIar50)InKd(5Asx-+lLg&BNi) z9zGAZeY0!utsW-77{(P$-`jJ69=-`jIy_D1oLH&DL;Q#FWw z*eu5zh^j|kw#{~n?M)w+75?)>QX~K_%=-exj=aMm&iP-pa+5#*NQ@@ zKC%748jHr?mvw!N>Z4>KvG5bf3Y{ z9*sH1W+!OAkPuycK%PLGg~;K)asn*R4-}&Q^XFPN$F2{XZa$U_h=XDZ+6t7zNeRfL z@;wdk>0XNdYwcAF3%Vm!qg2UD22TG8vB)HqxArj-_T5Gt1jJ4=xk@Ei24je0~--5#5KeM04=@G@Zoo3S}FA_p|QNp(NErXbB}M8Pj%}0zJD<3 zjGNxhYRq%yiZ2)FKm%z=M83bjXX{O*1wRgc_WMUp@g?`hOuSq2f2!(gTWg*Y1_>hN zYwuwZJUPbIU-|J`{?ad0=qq#gWAdB)216pKq^cCdRK8ViD)XJN#iF5&7G7hD4-|)< zw{KNaY-M9v5hD&sKa7_p(&xsc_j-8cMy$i+^r^7@vIexEY1o)l#J%7u=z$`KQ zb-AHqIW()agBWPEi7?&6@AvEWo9Yj(`ZD*KXVLG560_F$le$D3os5@LoQ$;Z!x0kr zJvQ7*h)9HjJ~SVc`E!jXKgvqBNo?df0kl)1+nN9)r>eU9V{**%U99zPEzoI{wx_^2 zHW!63jcPiFos-9RD;O6=_kWt-aUTa*Xj5)Jl7SpQS1Vz?q*LzhPR49}ieyNqw6J3) zGvrVWv*w~-v9D}z!U|!`0uygCLI;?2tO;M8#F`{+WE_gpEOp^-U+vs+ahIjj``{F@ zS-b|t-&DlVOEnF0;q*mGIhGG@*^*Jf1l+6Ns(RV)H>5W+J~&zR!0c$a%_()?5szwNi3ffyor-3DbIAHn1P&LQ##BW-zR;u)t%9IN7M)+qDWU zsK^N(LyK~^F>Gn$Qh%9R*c)aj;X?7!WkP6MjFF%KI43Tw&FJ0j2&GVLH@i+VnhY2R$w*O&M zKS=0&R(CP%x{H~uoH%fA9~^XUbHKI$K$t-gg3uIc0!KH8Wq%}Wun^eMiandpt*cNN zy8ZbL@xgn9loi>|3ChY*lj~}s(TRgdMZ};Yc1vGrt0|-I{+I|1eI@?q_is4t*+0w> z=XJ*o6i1w_NV{8PiNnl3748<@GoH^DeqB83S~oWEs-U?h21wuz?TM!JZj6LN=R2H_ zXeTGTG5D@rG6+PC{n}-S{aL z7ZJ)F2g)ec;>PC*L|HwKH@bvUY`Kh|H#)?`(#6oFQIr{&I>Qt(Leo#&r+p>+pxhJ@ z;}^j)$_+72k`1aa?(&UqGv(MZ0%VT>-KD= zPY%7lWz(UCtj*|f>|}1+qrECE?n%xqPKGf*o}}YMS@f7`#hME;_<3PzvLq+8wDet) z^I2oSJi`eVihG;Rt3d-)Q|WR}z~LmGXQ;|rK$c*T3T&1iquXPR*d1LR>(NbG8@G%y znSTm@nDzdC{xmZ<3%v*Y!ZX5gh@7)n zIPY)twt#(6=!hD*T(75YUM}OpQ5h&{P%xWvYp0dCB}^2J6-|A zc%W5f&=&oE^X@356X_G&oe5zX^M^WebV-g3kN0S)zPSrWYh-cf)I;|k334Q=jsr>- z^u(Sd%HVp@iI}9hlD23Y?1eD#IILKrE*|NOMO#8xa|?FusghbBL!A+#Tp?5w34h?N zm@C-Z(z0H0@) zw9PcG8P-)U9a?y$7sG3P^Nw#@N8u*lJ6I8F$L+4OV_Vk0(}mqVIjT7dmtMOzJqy== z2I&Do`FAYA0r&>yIh(R-2N!t4Mt>32;F@;cRFD zX1Z0&$x!)7q9uLj8J_4MHhL|JE_ECYoQJrCKb2KVM47URiG)r$inL`FqbF5lDF?ke zsywTLew>^tCE6^t<1gFV4%<`XoQ;O6`}@XyT7C;BZSkR7>?=9)VnQ7GkGn^mBW%fVWNYSUZ*%nSyWO4~ z0R_4yqv&Q!3$j#SBjRzaEp3QGq6zBx3$NkSZ|hl zfHVNBA5V{_9xu|-F*_dP=6{4*14oT7flMQ!WE{hEw%*m%G>!-cYseg1+JCF#vbX}hwx9Ml zEXh0m)!|CeSme03o`{+kriv_M2FvZ#-3Z4*4Y5&3w0g5A~m7kFe0(Gwe#bpO6dK%0)ta~NQYJZCh(%^FrQa{llEh zaD@aWp_@To&IdT&0X-T!iWF5Mgv6=+1`36QR;+?FY>3eH*`xw4^<_6Knk|dj??xp= z48{vglVO}yaPB5MiRR}^Sv(@59d5Ex{a&xsFB-b~fJ+87YT`p^*CHAH8jkeZJiQZo zq;2!i8}hZKM1S1bx0;QRBX>5)G8{v-mD4WM+J%sj);+AbN^w11L+{eW+9nB#%O`ab z7D&u`-pz@-uf*8;uK3o|&5!|?FvCLQkS;^$Y^sA69auyoaumW{tuf%hTw!$d-n}f) zHsARiN$I?#FwQGFn6i-kQe~i!#l)U9zZa_&pOdGqeSd4LYA%2)32v&yz;2?i{c{y9 zd*N<1>o}q(aFE^0Y{(^_NRfb~Dex~AB-@$mHd4Z-Zj5^jB;!DOMl4IO3$(E-+Rk?? zx$*|)z0ej!0k*r8hl3WLqq@6A@5jax?4+e9kVy+xk!&d!?*yQB{9c?5M~&PiCPUij zE+wM%K7W332YF+r!1{v7P;{))McKW(57~I?JntzRHy57|kbd)cWq)08IRC)n?_x42 zmDu87Sju$UenQ!k!srz}-mbN!S`5^{mleimbB}ZtvUGf+puYWh15=nc-GfSl&vh}B`mPoa5A|NY~ z9&{X(sCDcoLrg${J@ixhyNs%o3*aj^dqXL2k?n=o$LS;xM9>xKb%dQk`EgJkYnyci zAEhxNh^E%!+KaQzGSyK7IR+H0q|HDUq&Ax-N{UIxIm12ck?EJx`c%Z!q?vTqs%v=Q z*?)q#dgRg_Zb89Tb73`AP@q-uVTR0fy6aBP4d&bggZ<_7D4;6agOLyT)3FmGf5?-=qttqpQAA?k z1-?Tmov*A65i^_{DDCLST)QC6-?5^rTz__Ag<~h2*W}qw(V(CyyV0$3C9Def{qJ$Mn00kH7o=@zLnvmnFm9QsbwS6$q3vBr>oa-G=GlY~VPCTu zJIh9ssrKYQOP&I0H5{&?@MQ-g;em;vBM}Khvc1iE% zMl5gJx;PgP&A=yliU@>1W-?x2I$^@x>~;C2XbOx;1@&=MO6Mb$}ns%47yS-=RQaGR*f+b=knRE)19oS4KM4-U|4N-QEapg$C+ z;fbM!L#%(UVr{6OzA=$X*M9=lb-m1-D_pf}wrAQ2W}^c}bqi;Od@vgoWB~tVhYwH` zx|Taj8_zj_?wK(h=JTL?S|Y5rZ?(`iwH&6Hl%J-ynex5km!>)s=G8H|(_mWaWRt6j zl+el?_@(qEPK#;@TnN)v@O0Di`7e~KY{kJTyYs-t87+zlWE@ba*s4FW(*D@qIEtUy5qc zZh~@H&vRR9_D_upj(X=%)x#|ZSdWpVq=!u(szGp$SF+YQiy zad^Z1r~tLC*=nU_7jPsSifxZfn&Z}{|Da;NbBtIYt2Mk8H^^!Tk!$s6&F6Lg)iU44 z&)y}W$;37ek@_d&N2`#D7V_A`+@Nfgi{#GLjyY&y6k+$EmVcvLO$K>3;1d#)u##02 z8)Jr02Pg`N&>=^y6BD{8p=J`H%Njp)S#wgJYJH0h>4k~tk7b;(V(fmYKq^oGoM#xy zzDN>JUT@E=Z`yIu{De0i#)Uu5({XYDV`syO(Xw?Q)~MKwu(1)(*E*IjiB_-i#L*rq z(8ZT{SqSQ7fPe8|rOufT)$ccY+KzmTg2~`JBNq=@NjWA1+E9Xoi&4^l%FJD(_(Rte z#h55bZSwi$^Yz6=f7g7I9n6bu1Mk)rPvM4|@NKPjxh=dsdNS$3XZOlfALB~%{(EH3Izv0$?M@C;n z*pzOjVj8rgDDVeQ3wpH077+P9?}uJWkvza_x74V`)9dOf^v=l@_7(O-nI$(?t0Z34 z-iwQ;A%7O;?yh(e^43U{;$OeJM9h#8io0P$&gE4ZUN-8n~}cPDy5DxeZH=aw{IInifyQqf+=2 zZY^=4iOlP1sWPv{mFD<4V8kWsh*f48mw#>mIFVeqg-JE}BFnWk(?yJd{TIn? zK5DAEjlF>tx8??|aegQojYFUPt|@&M)av5NQVDV*#hwXY$S%mph@1INgX7XPmv`E<{dnzMVzY*7Iji+b^p(0^8I zRMFf7XH9cbf)jqVYHuh;J8(muL%dojgKhh@s0#E^PuX^^s@Q%J$F{BmNP`;(GnB3%5D!cws76kj5}fq!rAouj3ckrtlb z#MoHQTZ(?7SqApX@`*A}GIy89c~Ll@|6|?Awcp^1)xB6;&oUodJGmNh<9}0%_|L!L zYc23!fAk$Rm(L8Z9S_Ok#D=IOo8|!ha_PE<2@dmsl<4 zj=dC_i$M?a{SnDn)BWFy`(IM7U0dA_v8>J33^yEd-{@XZ2A0UhL{$$F!|z$OUc$=TOIto7 zc2f3uj{?_`wVkmUH-Ev>mVsOS5HN1&NIwp*&Xlc>opL2_K>+35L6N>#n>lVW`p`;c z^TM!78U6P5Q)Yjw3tB!W``cCXA+PhRCcT9d{-v1lG=eG-lLp6W^fQ^DMGT1>(i=}k z@V`hHfi|c{CLBP&gz`HD+z8uv_>UC_6iHflL7%1gGF-1(xPPlXwblN@uGky22#}*> zH{Q*vMLOFQ%g2R8)P+LPM-R%hlUQn>q((@5o!%CC^Zsjz&rv^Hkjvqg1+ALZ~l!QKh6`SU~iR5%YlH2OWb2l}g zW|PswW12}CHGlB0H++ggrp7fwqYMZ7^s6MoR8?5L3N+tOW_pCJFUM2+DxL$kiCAE- zg(=)g!3vALCf|N-gJxOhA?;+D_Vtx(WVuCnd9;udb_UUz9g6q(q#oU{9H`wK{??;w zD~f!2g6XwL$9yY~Ewg?yyN|lQ*96E?y^=(MCSarF(|>^O=CLK)8w2sN|NQy;|IDI; zg?P45;Da6~LiMJI+YrV`2JD^9S`pPiJ@*TC!TD0v>Upz!7aDTV7MT(SVi>IO@4UlbnBF%jI>~uyd zUQe7jQ|Vgin5m%Q%b%Nzth{yX-)@EUPgrM!O)~n7avb)X)JB+hk{`Z5u7_jI%H=1IM{`?TUF&MAWpP0faqP|zI1 zU8q($Y~)iMO|g&&Ydd#|mVKX!ypwCYPt+Mkj|sUQ36hmCg%0Sy=r5gjN?ZO!WKmv= z_yY@=o1wVTJYEE02im9j)9+O;@gaKklz(JcdTnI zyS+BNPp=`I_Z%@`;lIKy>8L_J#7$0;8vZ(`-WK+3vRv9=QY2Aa(42@!n!=_?d{V+8 zX>8g>79f&lR+Sx6#ys(X$?x(jo<`9(lIH@&Ve|d*=S&$ug)?+&H#I*|K$YF)>e(AAVR zItX5Q!Ve;33h-_1B2(*1zR|jj41aa=teh>X8pBxPx`;2lOH?T~O}5FmQDc>pNJlwpM>#fD;+MTx$c*|2k1Mds&fg?Zw@QjD0`J>*T#A#YS2 z15#Jc!&K&g75H4OvgMF3eT%yt9sG#GV1>}LNT3TV>3r`AHze^vB*bA*J%18`>wEH2 zKaWx+zQE(&%l6P|YBgRMNf-7^es<6Uwnmm;Cr6Ljqsb{Vo1UIbjwp$u9_chTeE8^; z2?!E3A5E}W|LVwFTFheV>7_7=P=GLl+{N}SjD}Wzob+N(_Np*I3^7q64dn(V_$=`>6ADx{Z$0vXPDtGH7T-;hJWI`k<@9X%dz5RPwnY)XV>u%B|?%C!d>?RD2BgLn`; z#fe=cc9drrXJ9ik+kYP+ZD%(9U+Hku7pp{va$vS)kv)BxBxs4)3p}r*;)i^5EBlU#0ACtaJot?SBx#5|E`_BD6Cj!r&nrn zBYCHqqC3a&8HqOot6EgLI#lc#;Q2n_cWmXUk#sG0T_M7((tj@`2$DbEft3(zr(bH& zP9JL2yW1ZD3gvyLjc+<_K&chSJ$!o_;LFM917|z3sAIDR$er#@rj53^5(^V|SIId^ zImL<_5nhGTjrf(x6g)tHX(O4 zv7rSECp(dMAb-1IR)ilVK(%CE;?z1N*RHTn91|-_R_!jTL?#lP=mS}GSlC)GtVp)h z5DpfC!eh9LgLVcrt&!D8Ruih;?4Ka*iG8`+6sVr16}>Vfv?I8Hu`IBtiDDTjD(9+A zHvL238VvPq(Zz+;^Ons@dWr{k%$Ar*v7$BefZ&&AZht|Xz~9bhbtQRfXFGjaOV{m7 zfr+!RvOj^5c8+UE>(IJQdGZa*MPk@E%&bI{16M$?%sTUJ(OZ;cmbCfU_tF>F> z`E@G*ntxrv{xzn~fAE_Rm?CkTez7SVPm3p96ZuYnKG7K85|XbP$v|C_ntur-njdLS zx?pq*#sR-%O{e=bpL&x=hVSc%fM-F|mOyvYxF^n=h$5E&W1lz(tZAzi8ja+ax$KQ; zPxrpQ&cvwa`aySuaFrWO)G_w#C~0Cy?AD9d#(#Q9K5NIF#hE-r9vH9T7r?nXVb~;) z?cBqLsC|EO*vyZuCu+-4_HNVW0DSgI-BV2-Z`{;$Q+xltUekY0QcTxE&>VEbP2sko zE{Y!S)jri>z?rm53ec^hZF&1#rkzH{I)D-h2sXx0!V=p27@#?bVX3Q+g!YQmnkcAH972tAto3&rLg0L3C?PJPE9p3XiZa0MNb3 zabfvuiuAN_T{z3p`6b1p@l_e;) z42$E<4j>gn`!tu!-YZ^|`ywTbZvow1@qhY~Dykp2?@esT5z%?fd*yrICLJ;)UA3-fT-(g($S_@liQd;H6;<232O2&@*xkh_M1MO+ z+lC?P_4AHptn)s^ly5{V#xs6wnV9H!_*)#cN1BpF>85&5-69&aTw>QzOdP>UwG#I3 zDqbxPi_+LF{T6Q!y4$103G}t4=AV#-K_l~K47?W`#nY^ zk~UcI%tStou2Z%R7w!@Bb%kr)vHO8MzH}W*9Fq|_Bri;p!ZmE;f^6z53M`sXE%}kv z6?4~#$>jEW@0uf7&KiRG!~`oCzXtS#NkEl1SyZ@G;jzbZnv!Y2S3 zY@xA~$3~gUifYJ6Q<=9&!qAkDuJe`@b*)v?KuHidNQ1=tjQU5LgALAP(VB7R6ai zcNm}({!4j3Z|^2zu8=}D|7liN%cZjbe&havG%k6YPn+Y|n5&4+g966fd2q;%dVqQUwfdWI8tA9}^j@h;a_5ja zTa|5EYo?GqGmr4PVhJHn=-LWJ#b8P9*USbe(N3V(Csfd3)iC}Ed;bugk* z5bWf6D6-J%>-g%yM~rcu*pLr{i>|{VX|k>qRm`(#7yZqa;mhnqAp;V=`ovS<0%S=ii5@I`ss3X4Ybgj?Ba?cd|_(B z;B&Yh));X|Wq;!rX51WbD02ffZ_tUEEay1Xyunl|Fq}cz8>&g!_yrX5`tELq0&ZoO z0^Qw4>Fd39^2$@LFF@ji468{&qS*E*$Wh;`qcRqWWUixF)tAp%Bb&TtfdDZOi6E z@E(?S1V|VA%{gHMqM1SSY*p~_yMMO-;aqU0o!3B^68^43hcobBZ(^n?jlU{Gf;gY%|p-;!hXCEUk{d1 z*T`s@;uC($)2Qlu!|NoJ{~Di;nR?H&r`8;p zEsQV9FV*in9Dy&Rmvb#-+Q5P0!cjS|FDVXW!zRK!gZnc{ip*b>;-rOz#eb3aUf#s` zc&_W7zJvD1nwbU<)+U?Ga_uV4N_354zkgN#p_}$@HEpueSr_#_oAZL`N#Q%{D-hTu ztCvryn!*9GvHjk0U@R0O(1&V0l3fC$3lNGUT{2PuI3x&%T}a@nx-!)6(x9+jrK~}7 zQZM@x&mo&D%xChqDqf-UwwN{P?Wknrip1pke`rXg|BJ<3T0(d+*`eB?N@rOWy#{5uA zw&8HETO~`AA41@k3@6FqQRkVvv3cfh^cbIbxTiQA%Icnru2KGuF%(9uP)L^~|{`+{1gqWGyy!*T{kUudSDSYl_(dZUw{4x z+m)ER;e&V|Qif_)7XXw?o!-Cc(JgTnyGj=wcNqykxRZpgcaNSqchS$Ei1yRhDal2Q zX4x7;p?Y>g0CDw(gAfKmyCOD8Fha0g^w1gHwlA%+a8WouXn!FiF#ZQQJLej3P&+2b zGc23M>8VGLAN!&?Zv0<^@m+X`k6>owBP5t{y2 z^SQs2BvHi3r@jW0KH|Hu^C1S0@_`ud*N_ea9k2gC1{d5=-V-GU{nTi}lGmfGCwst#|{G z)b9q+@nJbsJ77rs^mzZF`;C~o9mpf1q4&9q687Y%#*D+5z;x)`v zNK59npBBvX-`n7;w}USp0m5FeO4k|hKE#&T6jzsmQk16V(^Y~Zrj0z(r<{lq*Qa@V z+)LH6hY7btYm7IZT_Tcu-xv5_N;lr~5HLC~Y~*Ruc9 zmrKQ1C4CvfDBm0F20dpt2BQ_mO}->YMg_4I4bkQxc_PfZy38NFx;u5J{inks7Is)f zPGJ$PO95wrZqW2vm$emP*wv*chB`AV=-nTCoqDcArOmrbS1xVoV`Y&^Ez~An>?*$| zPJjG*$Vb-<-!#90UpG3yr3R8Z>p3dZ@H-^?`|b-^xg9ISHZaW5t|IsDQc38Q-5g;E zOJ?SN7Rq;?SJx3c!MWfpfX!F2+Xqq7_hbqV)jsdJ!bF5YG%DJrUI>|xIQAlGthZ1Y zV)4W`!sr@}IQkOT;^W)xYRJl3yAB| z{c27~CN5s0axx@Ub9j`T`ZI`iu%`Qet@+tmcw$@3UbdRZ3D~zN&}`2kQ1|z3R94?e z(mCt{J+&QV{`%xg3VhOv5AyjxvS<<=KK-k<+V4t*w8JxB38h;8jO#8?EjDpn}qmjwIh(sr4Z5v4LV^JvW6Uaf&sQ7RcGo$fQ zzaUDila@u5`4w-_ae(ZB;%Etd0=W#CX){~!tGpRr6|=f(stcg%;qJivgl(5=#nBUN z3t#0s`0IcqI+0e=Ay%ibk)PJC8>-uV0Hd%OxBQ?ZskGSGN0hsUZu|W(*5ECU^ zqN+fbLs9Y|4$HNU`~A@{USXeLCd__?xh`Cas-8E+9~{7YFo|}S-}TAZ*jC-pW-;8Z zA|QJ|1m~}Xx5z(xZ@qMV@usB|9L=*r{$eF@=#(PbFtR1f2w7@w!dow75P!HnFyUFg z%A}+Z+IANKi+ojao5c?m@0BDBkV=0|lr2b+zhGdNyoi3&`lweiiiWact5|YueHaQO zwNq=pTEZER597fDHh7R6UNS0U_YeUBGcuxBPg5uARw8sl1SD|*XdHpHu%tjx4~Ib5 zGAkVE4!)G_>fw^E#td5%5`P_xabxd$cw0!Kl6ZT-(EwO4wk7USE6=T!w?#K8?+jAQ zpp6o57r~A1QZpt0!xaY27UCaUc=IJF>_MkhW>t&2Jn81E^qP^aUBv28IT3?+9t#bwuOVZYSOS&d+V zDrKt*Ocm>vbh>_lb~~1$#JLxpl9-s8d|XXL0l^D}iFec+mVb)~*}9=~ep!@C+bazH zCBm)S#*d(VtK0!fyA;}R%Yvo!4QRZ4lzit|Jf@iZ!i^%0aNrnM`*RhU6+X#N;|4`H zqZ=XN^2HF#n@bb%6=xuLPnrRW(1Dtt{r>vm6+ZLX#fE#`+4bJU=618&j1%vUZm$(- zslkde)Lu~R*MBDe!sDPClW`3_qswJ=o-dy*R||}aZV?p{#A1>7agF*_qvORk3?O^0 zRJsLGgm5h!`=&*M1X{ANhG!QfS?+@Qm|MX!uXchW^lL|UiQA{>rABHTELB1%B4L{t zjmz7huRzC@Pl|tmv_grcZ^9Mo_t-jX0!c|Jz-(PND1QTx8gJuP1fzLfHpQH4Z%KtU zP0U%XAGC@)_#xO;u#ZW%4+>O^@9YL>#c!o!HqwvsB><0FoEG?y=~fa_QCv*PRaPo| zT$G&4TTm*N5a}rAzsCf8LVoOcA!Ix&B_!{Q4u13U7d-cYI`Er zD`|YJAzi&3i-B{3-zP>-M(gf{>k*gk$72%i!$wbQHf-|&41M@+CcMP zzC;3V25TAY|JzQ-oK@GG-Q>MfBpjP{6Ip8y{tHhqGOYg z(!Xd$iK+%v6gMa1)2uluhm+H6!u*B%)N=HbZ(uAy#SAB6A97YJ->5tr0~M1`bEIN` z7=J-!itvkq5A6(9JJY~My*0tdO~izN((atMG1 zf6_`Hk95zWh@ru=^SZx*iQWf*TSj=25Q!r-0*t{Qn z{eaLt;hlViX)1+`e<&NNgbKY*41whpr8gGRhIE<2*ytUQ(-rGNJJz~&+V z3Jwg3Bj3DxL(o{ya>bOi9O=Agh8iOQ1zJlg{p5qj+GXboF8jq#Km}BFI$>q?0+0mB z!unksB#R<#f&`MY-C~gi=2=J;I^~iH4mANR?(XrT$Wd{F0eEOEHp2=;P!#Fm6bA;6 zV0#~+B(xd347dr8VFd|owtqwkZLBb%&9*q9y*tL7=h~$|>@JZ<8*vL*@kcvt;bUDh z9+-{tcOHon(#PCsooT;yF9v`=1E-QQ6R_T&*Hn_(@31Q+InqxK$IKCrz^NwzSq)SUlJDUK*_WXXi{QB&qi2aXvGTQ&2D3<45`7X zlOVu2cTP*~d*)~!abW?ieg_b(bdjo*$TC}uEK)KCG7gB?lYjOA4i1HYKvFu#7$o@5 z-QCG4!yf_>6$k_j{!C8yvP{&vyK8}5YlcUOtf-12-HMV>o8jrMra|@g6uC7K)&su? zcR(korU?#R;e&lW_NyBMQIYk&$3DNHle^$-TDQPihcA;P!^Q|^qKpn=h6#ejw!cPV zbR-1MdQQJ!xPRD^t=Wvtvy%yX#E#exr)=c|2%em!S=*&zT>ujC8UWgV<#G;qmUyBW z#Yd7+q4H#%i*!*C{+!wEGHr$aD(*b-1)z_kI@OnvRIj~D9K-CaDBeRmj$ z1s3VlFa8kZ?h zeVQHZ?|-*e1MNxcG|-9$HqqF0vj(=$tzn@FYkf3DZm*eh>sT+m23JlXdb2&IRV30+ z$ZvzW3)|IS1*)3m-$>%C7AYLoR{Hr{!R|N?L%K_nqLF-H{modM04AHS`tT*s@ov`c zBJ#F|Wdz8a6Sfy31T1-yr&8=tYeJ$CzJCWCR!6`1)u9iPscII9A;MpcjP5LF z!0$KHUn)XHU~Ro>&H`(%-~-pz<~aHTC@_4hTi=r1Tdi|RUdo(%X44V!=b&}0Gn~jb zTN!mP5S+IAb;8IPAW|<%b>Q2`WJoq5w^E0N4TkP;S4=)|9wmrDiem)2`kTP|!Yy6wIe?`0B?ryRTp zg>eB+K8vVyu{PlKG(pdOxv4>{tGPGDX@4f{M1&Wv*6rdqV01}m4+-x8Z*&u0miC@C!1qSZJdT&oWn=s@%N9%lkXoq{LYX+Vvf^(Im$_aLmzT9v84$zk#ZnY z4wN)<$Crb8<(3X3i&NJV5X<99*&Lgi<0wkK%kgb=fEtE~MMAF4lY{6Pd8je*@0d;C zf0TPY98D6p=m0KP_|QTRDUcGMuzzvUvo{0N18N>f2BKOYjM>q{$3Gr@Hy+EdU_JJ!M=xLfeD?YM*~e!uAJ}_`yPj+?kuv&v zwDi+TtzbM9TQhI%u`%XA05F~}*F*kPXzs7kg8D{(-r(o;0XkBX&W3XJ=YNersWX8a zd(_SX<^}%LT4t3X;;d!rv&)N$ai^293g30Kku8-c(Ubk2y~{)_Xbe({KG_C@lKHFH_k<~%l+aGJ##n3zjC&p zb-8sGY`)$4+NTYUj*yEu34hPPO4w5!-@2A%=~jVP76>JBcto_f!LDt!o}mT7`XHN( z6B01yA?7QW%oo;PW*(D;60Tb7Ay|{u!^yPP5-va`=zK9oK`DwxZQ1N7Y_trIe!#}>&K-WvVx}|wM+z*lIn8>q`(sg9~>0k!g#Mi_{-CaYr_(9 zAJgj2e&*G`e|rBe`&O>K>w{sb(lskDaVYS~FY`7h9$NnHI~%^Y7zQU!TNN&}!PC+h zgYY5?2rntncZ`;G)fESFkvDgD`s)UNtJd&0xf&KFtWlGA!+&)HQ6tW`^g_z&8mX5Y z?W0?abE$qITS(JF8bGeG9)i3?@j)qtlteJ_Tsl4~K9c3e^h*ueYARD3_YJMyLO(e3j1@vVr}5F9F7;!U<_12U%j6X8MkZITZBV7LK)*?jxFNDg?uQ8&bKGh;N?W)=mNo>l848h_uLXK27g-_w?mehl zidZ_gv%KLEp}Qzms^qMQ*TA(LO2|VBvYy)C4V?n4^N^nAz1q+1k@H>9jM(A zGOM0elWBj@-9NX#=uWPQ*MQrLgn9bC9OL}U3DXrGrEqeOU|H8%JiE6( znJAfj(k_5*p%J~RYnWv8y8Hr&a6XWGIS}shqezdwcRUk!JeL%%qqGln0F(~9mhNm%$BM~1n4h~SXM;ggIObsi&38GPG;9%s@M1qb2!*ukT|OQmpdYf~?(C5dy$q zJtvTQ$C_n!Aerj_{A{{^(Im*5x!2!gQxuUq6y&6aBe&1enrCg6n5G|U4wW=t$IkYZ zbNr*9067s8xp=qSwwC1mE2}NEKF8-J)HGxh;X$@{{Db}pB!|73Y z__&OuEvvc>)&Jm{^#~FTTaT9h`vT}#Y~YPv>V@Y|+3!!g(egB2cgtfeR*-KMYVZnS zYRK(}lC)nkb|b_1Kq_L#kCHTj^`i&bs?g%EuSN{7kB4*A2lfqD4$_${z(Rfb+W1I@~^bG>+72dG~FeM25lU531S{Ldw!8hi21+n)hZxX^&Zr~ zjG@KcDLx`OlDi>SYH>!L4`BcwGhL*y`BUZr%R5~$rSvWvpSCIZr#!KHT}V{cZ6`17 z5UG{|h-@lEq72e{F4P6c{m2A|JpOq56vvCtqeqQVfm1I7W{TY0tuN$p^n}X`cj5^4iQSAvGkHd+ z4|vB)3O=!rBiiTnYc{r{9a+mtI?;{eL34KVoycrTjxgRCZ~pst55RFTXsgBXgIcB6 z$h3I2QwcijqYdm=qeQ2K?E9}9VoIH1S%mpm&R)+N3Zt?b#gmGnSG@N@)JG@Ip-KO&=|6zot^ zn3xwklE0OHN3tAd0Lb0K;(L7C+T*gIQq>bM$Q@+JfA8><%h--ujQkt3X0FeM4HByI z+y+aUQZvZfw0ago-B`y(q7tU)ss75-`%==qFJ80mvOmx~L4HOUu2c9NM5zrmlBwjLU8QJZSRFh$$U*Jb{ih&*mvJ-j%*SFg3)1hC9Sg1&XxG%QKjkv;I(B1dQy` zyHDbI6cE7)4Gr`jO*SLq6M<1}Mw9V^CyU-D#K)npllrxYDlA4=piuIm7*))C04$H^ z|CSM#-lXY?SPYa1*0zRnss?N=<8J$W&YL z(R>*Jq%>bmU?OFvxfg>m zbC;FT@@cKfTtViTpaT&RXMqY((^#fL!iK|5ZbfQ^QcFhv?IKVau3T z>CA8_pf^EoWedOh??iWdGABgYkLKV-Oo>UU!ajQxOkp1FJ*wOLnWcO2$DMx(G`icT zYLhrIJ6Si`M8-jDE}7fI+*F%|!}h1&mbVEx<#5^v5nb(8liNsO_!lF?SF>o2=5^G5sV8Po3+sn^Fx}|R3P;pl!6#BI!vz{@h`%0sms?Nh}zma*;q3ZUZ##eAMliqXsHlEnqJ>_ zfEi{YIpcgG<~oy4xH`LvXt)z}WKWByV!e~e-kDTE7i+3u!m?1p%p8}*@IJsXgts%| zSWVAMeTEj}x0Pic9Lmi;QG}SlQXU`@N4uwK3>v)%dq^Q@2x{Rhp($Mic_H1XiDjO zFcwPX&B71(oHl5Si@`pIb$j#W6~n51vin&t_Fm@xgvCMHc;kiMvJkczugN(2FPDGFy1=32HQ&j^wIm6UTLJ@z-h(~Irf~8DFRQE$Tkdfj2WTe+w1ZI3#TsjYLml*f^DrjsN0exhj168ex`aTCbY$l=&cx zW8qat?UO+S6LJixH07!Di5d)CyM#EM@R!wTf&qo~HU{*Ka*0tZY!S01Q z`thu2@@vB2^sV-oFo6KhxwgaoxgsqhX}=OC%jJE+(Nux?B@NM5~5VV@O zyf?f*dSRo+c+6O_IMrKQOJyB}!wz9k!l~eproF&)%B{h)<<;YIhVi>KO91_Zl!(yD z%60yaY7BK|E$jIz>MN0;)BmGI(`%HGUh$vBL;ItSO(x}(+8Q5A*|#Vd z#XeveS|?MeyxKWs2xw{e205MTD6P#P7bD)UZ9}TGw}6}3bS-ni3ohfvScFimO7xaP zkk8kbo3le=-1;NE1nirIsrtN@l-H^CueFDU8h_KDUQvw0S%SS0adf?<1VHs|VvVI7 zASP;8On&=<oceY}&(ll}>64*2=*NG27ZdvEWq7N~@C+>g9?u zyo(GXgU3KCwBt2~0is4L&dZ2wvJaDXQtuyiYn!g&y*@AaitM9V!e^v|f`iM#91IjO zc8VqlIkBBrbA*F`hlXZmR$Thgp*(0o!0(S&myTLNwx2@FsSKLnUHLQes?z*@W+;&r z7B>-^=z9}SUnEE(k6%Wugc7e!=ZJ2U)qTEP*b$uvx>Ll`v&J~=ibW?Fyq?x~~=7BIv?)-^A0!5BxFetw_jhCXd_U z$>pdekw7ifQG*??CR6DA*sh@F1l;yl6OF!g60b3LkQkD$bDzYF6gr~*`E#EC z20UFC6#U~V>%)_-UX2`+GGofFG1;Cl5ODd()R~FGz4GqJf~ zMp3C3Ix8X0T$(!4x$9Z^slal$O<>3IW-GeSr3sSU3q`j5K`#k#RLd~*w zU42sUa#;EAzx7Mv4Wm)4=lOj)<*;CI!}>zt1CqNq4On)U1()lK+EM$)=%d-;rw@2` zO#DYur{Hfta!aDo0mGOVv?JZBztSgy&7PrTLt1H5=*w1@|JNBmbgbvwC0wzc_!=1kkfD#LM4QZEQ~d|hcS5<@ zj1Fl&+j>vIS#1BrzS(%UB-YV|W>YBPY^c$+S)q%ct=8DZqN(8=s;E@k>*+0AL&u08 zdQ`lEr`xzy0~ikkOx^tJ)&Cpx8^3Ee{Wd&M@E1KSB@5?3sME!9Z1`Xp3734^Pv7{C z;O)qBe%46#d8HZ164a1JfF z!8Zk6&l7^jiK^LFiOR`A*Z-_QW&4vS;z@Ga&gkx_ZIA0XI5B9paYUQGh@ccNnH~K+ zL+eAZkeh_iNo%z8xxMWR2ln#W>0stL54B}u?D}E|D9+mW-cc=wOJACk1R_nv*vf;Nt!hMk^9EMDvT`C`ebU9Z%;U#Nx4pt|V-ZMrhi4x) zN_pfa%?OqAuszEhxX(4eYwN!aFVyyPWx=pIEoG6{mTbd~2?yGoVPc%b>P_;IOi3GJm?F{yC+JYGhC%X9yje~dY6r-zV2&WI zz5+LJI3%!4H@X&0$wsNw*#7AuYjGVg{|!@sXZPC!kK}@aKOY_n)C@NnaYKvPGpGbJ zY+RV9slUsfou*M77fQ<74moDM;D_d5l{o!&YqaW?Ff>AKAscds^D??dS6tDFg(C&Q zeD&jZ{bV?uj7RDwC)utsuJy-=gOHb>`evc*vr|=3wd$Qe?XIr2Naqx! zq9E>XmugXsAhpo6Lc?-ZO*GK>PK5((TR+d+!Nxx98!<;w541JgS#g!wR+7GmSbmq1 z(vu39qwnMpq3C-EhdtD0QkNvn72H14Mgk|>mhAjRb_m%lw6Ih-d;GU&;FeO+C}}S3 zCR;gqy7Hg|gQN)xts4JaG-AZVb%V8+LI0)lJinU*HcbL7P+j^6+X_`O2iiO;Fl4_)`LamZ>uq?LluY_W#-T7zwqTgd8H&0Q-0xd zpB#N&fG#*BAqja&UefmMwUmJ;V@f1y^N@=moU0rg*N|K_Ch1*@G%>iJ93vT$Xcucu zB{EhpDFZzcHi*6*VS-Q;5ez9hKaSYLF;vrwpknFt3o39vymEJKxUIj%KEX#}Fal;r z6DKGC?rf7c-4nfg)#ojY9wja<#RhCcf+v^CnDuG-BF9EX@8QET@K}K264h9DrLp9C z?eik}UH?LTFWBlVBO={4nb8;LBDB0#tX0XRZ48L<^l;r`sD3ae%CcDW#jtCyp33eE z%I|#(2D50O#+3BhuEv zvL~(#rV1P>jIV%mAtxZ)Cx%0Uz~1|N?2N)CTwXr~{}kBnRUPo{kQD)1V)+nv5sTBB zLNH?~8O$#0i1VM)NaRtSJWgEFjHJv7=`g7D&yd`H%8q#W!clqV%$ayV)_?RN1BZnFn(YUcJ#Q3=QT?jMTpp;1l1!oVd~epk$EvbO5Bj5=G~!tFBRF1lnKa zP_vGrI{Z~urIPo|45=b>QL{~RE6!*XxyD5UIcQTP6=po!^wz9L)w6D`P9r$=n-Qa0 ziapiLQ2o1@NAVMSl6LG?T{UriI?d~5zZT`2AdzRx9rY%WukI~6eCzQyF4swA@o?X& zRw^(NtIh3~gaOXyKTz42?<6=9YMI(24=szO-R|rOh8K#L#;~}PB7%{!9)yP6f1tw6 z^=#TkO>ErYCHq+NjGJZ=0yN-BINkZt;pwpLTlWG7zSQ6=Ekd%>o-8W6#_p_`CL0U5 z;u86ORlttVl(-?8wTR1gcU$V|;YoHZPIF^ALO6hPPykC6Y*zo!i1ro#i%)bVu!RI{ ze<|et1`wA6=;IrYem`m(SzvRQxOV&OD%6FjX$+gG`T(!8dO5ap^F=qI-%Jy8YE~u1 z4gV$%Z`f{?*uiqFBil6zI%6ldkfQR0@{NjOS@Pg4<(E0CMfUd}o^>!4t8(HRnHyhi zW4x#^F98WkKe+jKc|)!_)*LNE{vF{cD4CO*#JQ@F4#Zo8%GZ!3C!)xVebX~t8qtc~ zgeGebb{jegh)h(TY@9Mva>r~tSWxuO&rGD7KK8^_?F~e~qj&$9Au~o}SxiIw4FB`+ z+nW2!*f(@qU?kjw5Ko+YIDo6`eF`Kt@)-UcAPDHu6Cdt^LZTk=<|L2^#R_+WPrj&d z__3Yd&ebA*ZVN$u_&7e7_3vzr!V-}vp|RMfzc-I-`=?Lo@?*%EpI9JU6Z1d($ayHL zcJ#f&ORhwQJBhPmg14?{06At%sfTjQZ||1oi!1Gz)=$WPp}jaaaNd)~R}NpgmK|AS zxB_pD*y+^|o%oHN(vu=;TKP|IJE&7|{jbY9KNdtB^kC`gjOaf$lIhus2xcUM5{43s z>15Vu8DBt9%UtTczPa?X#hqVy7C*m4Gg>%}xj5H^Mhr`vel@B{axG$s3x+0J>xA`bWu11#9#;#gJ_g)l3q2gk zgxyjoN_DNrbUsQ_GfhBn=9v(t+F8C&-jqj43_M#?!zPARX3B@E`Z(ADtax&%8W0#+ zj@UF?Zs$qLr!dFq<(?8%pk!Si!3N>HmIu=yy;%i=8%*+d9-?^gkF;lGs13`8$b}J- z(xs2(+Y;9aKa$;`K9vZzY8u!ii7t<}eI3V^PzUvjVmpEz`SYLAA3Mzz zfjK=o&1n>pW+%;}EpqCG9mEa9AwW%kT|MSfdMux!HVjWli9N)|MgKrfbvvfBwIV0F zt%KMfcXb^(wdDK1YKQtJ4QsyK*7uKfpCJG{uB8Q0qj=a7>f~YruD!|S1-nkoAR}%_ zpC4`=HZRu$xALyp4m6up$9a2{TnK$jvqN8yvD%quLb*vD!ZVt}Xq5Ek8n9xqepV$n zY*}v~GNJihJ}zLj%qwbUb}y-&I>V4IVgoA1*Povy?!oEgK433Oy@aPQjg}zym)j@o zp#!4ZICA=2jHvJE(7+OEMxQNJ^ z)fw`B>ydq*j6)^3{omXKEC8)F{E^s%wWG&rJ`5AHfUROfLx_!~XTa77Tzsk`Bojs% zX&Om1I=M98fYVxBsw~)d%m5e-*6YrVmIde5;cT(J^bn`YG|wVBb^yICdM%W;YE`F# z1SR~9O+h_SmU!gJ4c2wWW~xH3wNAKa%SMd&Pw=FW$DJ)(*v?F!C@@_ge_?HL0oC+T zBl*J|ugoQH*thThsrm*KHF(?Sqwli8GVVLTs z^Ows%Z8dTq|CuI>Ltt;F$CnV4ds&twL48O|MS=&-`^HL*WsGO&(x(I^vocWZeY8#! z){_Vhg_7$zZH7VrdxysnCbN+i8$n%-JK{dC0Ko{(*>gzoBvAO0pM6-`9#5WieJnNh zzQ4zZ>vZU}&q({=qjt7jw|guzzmpt#A!0pZo|#sbKT!d^6PWlOlSJiyb1mW<@D3*U z0<~p5VUF1v<&-MRljifDzyaP>+%+v5b-?05Kl#?VA72qV*L7rFdu!CK{#XAYqk$I+ znY#nOvURTUfna>3r#>Sx&0qiWN`l87SRjc_h`xs|nN!SvQ}ZX|sjni=&{x637f z%A2G#9&bUd+qUb?)^^a+w57!;rd?VEKZ?4;vRi6Bb(aRG^>15Mg}z5sQMu^I`&vQw z1ooQSz|0W>l?7?=jD;IF;v8KfL8@6!R@E>3%}8@5X23)yY->s}QE{I)ZVxdx?Y==b z7W&%{)_((zx>&;DaY{FB_o*J);?4=9uV&C~-H7F|brn+3dDSpa29Cp$!Jhx7n_qm$ zf3eRC*Yrt7RnXm(EUSrERh8&z`3A$i;}BZe?nns~4upigVQJ5TjcMx`2SsZ}Y^K2K zp%Fw!{Kt<%-j2THuhr|QQiOtF50jtyX-1R!Mg2OODaYJJ=J;Y~Xl7WT5CdMr!0lDq ztioic@VP`wq7s@-w?+^<+&p>c;+js%5(Mzyz>rzo-F-!wn3X*T47hMUm2{=AA8E4H zeUg953(TYc{B86KKeogJ$Nw2c%JS39!&2GnRtc~MwZDrN$m8S9PKk=uz@w>_fAuy% z=CPk)r&fi@b3E|IAM)h#2Ku%r)u{){1+~-1W!2hhRJdpwcK9JRS38^*1(Il;e}#sW zZv{bAcuzN-E2G&&=ljLGQYS7>n?oE{g^89*jlS`qM>29?-BR9RaS|YeqYN)+#N$p! z6$4{|4Lc43aDrJ;53hI(EM)|XVr;h3GBE!5Z~NUix;_WOW=#VYTC*55R!rVpWLR|A zNCY^Z$%luptxh0g+*7T%7_6OGkFQ{*2x4{RYv-C^3A41ytZyUp#5dcyGcK~6IVA=j zrwG3ceZfxiWsAwhFwpTPr7I;!W_Sz5cXi*$$rE>`wExNEAF~7(gz{kEhL$k(w*qYo zwdz(RM#rUYw~e8VUI81D(h2EvU-l4l9zxteX3Bnz@LL8yF>ihJ28yesiG(8AAP zM!cuj6rZBiqS<#T_M0T>n3yC|!|Vx3c|rJX9sT+nv*G7i0(S2~s&bN57vShrxOTqG zEs)~OMcxoKbD<@3p;box1G?eAAc7R#-jJGxxPlxq*^sn_XV&EeO#zlB-%9k8V#a;Z zQwE~2+8)<^*5JT<_i59As%~-)fA@#?VbyS1EnSq>g;Yq)a?Em-WRIO_8}V0*sbkJW zS+t4}BAe!!?2ay26bTPU2!Ma4`QKl$n!W~Y9H(44W#F~uycPDgX_laIQvxUsncZ|+2he4zG z5T66b`kqOnd-i8VXIqi}e7$7JCq@<(A1F^UTH+@B`)ER7|4XRmh?lOpmkz$(SOwLT zGRITt1W0YStB4{&1*j!$^WIRN%9VypAds&;p@gc9U>wpEYbbSUa3|!1HxtVTt01sC zT!M`km5!iRnzY~9Nz9;*?x<|r4^pxf###BfAr1Uf%b;5*}*lr9*6)L?Rl9*dze9=!e zbU`%K!OGO^)?2>uq<6tw&H>&yRK7j@r`I%-+dNj$9{}3s8HOn=cxgp2G9SX#MG~(^ z5HGqr(`Nb>aH>Ql&YTN%C+P^y;bMUU|MXLUj#hx+XD%gBjv(oaIi7YFscVihJ)tj zG&WV*`2t4JjxXo8s_YGO9N_Y`ppt}d>T>^7YBOXYTQkPa#3nzh@qTj-kiW`^=9Blz zuv7Ee2Xxd)>Frk1F*PdhDZgmrj@8gav!yaF;yBg3t{ST-aCfqC(OlFQfBOn$#)ff= z#Bei7_noq?^iG%P7ZN$D0dIHqn&k6aybQqwbU|2~oLaYO`24rH+v>!8_iAUixRQ-3 zMtY`vOrI0R=-Dy&0Zkd0?se2?x1nX5`Kx8mfCFK#_w&c+{c>$=iEx)@pVK8o_r>*9 zD6jBrdbL7=*0tD25?B^|p%LV&kluS5Zp;ADotQ^Wv+u`crNs!lG(o9vc5Rz(#k%~R z2}g16NFSVk_}yDH+qE=_@gL>kyKZOQFTBuj!aeb1Qa|WWQxBi9=#IdwW&_CXyx8$7 zfRRe4Xjtg?;-Yfj1bpWs_1N3A+zaU2=n5H~+NWFvqv}k;Q*f)82fD5E`9+T=RK9PN zH8%N!fiWyef2%Ry3Bi+lEMf=rJ}}+;Wg*D-a_md_aokv2s31BbI4DdustG6dhlg0D z+i@=Y&-?{MT}4{2=2r(A7z?Q6Zp_egpwGQivc}t9*Txk_d;=Qx-l$# z9HhRb_yMW?=%++NF@!$T{G?xOCl9X`S=~$(!dV|g^rq*+@-{LM4<;vMSf|BJz_Bq+ zK)5_&bjz=zkC6!E3I7uH0$+|XQ*3foI1G?lLdD+548HK>ryLpm`}}YR7`O|`oK}F5)Rz^W*Ev=!+iXuwIItk-s1#!C5!r-cjo+G}~Pt(A>MtSl4Uu;(lbn7J1BYt@S z{}RSy(i(My9atC{J@{&pJ<;~x02d2S)a29XzZwehA7oYX2E5Ab+V~q9q`5khrhY0& zPH`Ily%Jv?6hIQVn`-1>pNx$N^Yw4e{kSkxz&f)jDBxpB{VWW!b6u|g5?REpiYKj; z+enP+LdspC=7&}IvJb8G@2=@ZIus?Cy#D>AvQX)YSLEQ^r#gEjm;J{CAPQBujx<1i zBLYGaWW_6NF~kCk3i5h!7a`_WPUZW037aa(n!g+pW;Lq9lN{<%v-=e^F|}CfyFR4* z7OjGlTEpXrcz~`Zv`tu|PyehknT#!R#w=J~M!kLJzFHQr4)=qR%6)6dFA#KcI zGyd6BcD`15>b*_$;WsX4vMc{f`x&u|)C8iwrFFf@sk4-C;I@XXfU@~PZuNu%x)=9u z+NEC8x31(EeId4IQogEhdJtZ042UZ`GAJf(Y|g@%yg|zv`smyD>tz=DAfICBJsk}7 zss0ew1G2QS`sbzm)bo38r;5N#E0sT`?8O?JnbrR1Pdhg&{-u8v&cxjl=nNA`;tJo8 zvzQ>YlJ{(P>@3Cx0iTt1oYoWZ5RIHS0`h{$c{A1XX+xGna_JvUfk{20kh@>5Wo>2A zYz61b#cZ^*{m1VYPWbdv9ZJb^Tm!|WGIFzS-LTSp%*%0)4E4^UX42&$M-f@+GA*Y| z$X*nv!Dt$4>wSN7(ZoAT#tNy%UERVqZ|*HF^(A-7j47WpfqbRGE}W?`e>NAqfIYX~ z&=YHi?7}U}-#EKf%k}K<4Abxt3bq_oF+3JwJPy|%%TKD2KFWPDsdURXfywww+TvZ9 zXdpyKlP0~(m?Zts)s*YNr&wHBC`@cov$%q56DPfM;@ z3|=$*)DWy&03}MVjRM6gF?#+NUt?_430cnP3-k2xFc*~S%*Tu-Z)QTz)zvAMP z;fLzR0P0r^w)pa%=w6|JBMNsMAM@l!6d3*!~`W<3cKr<-(Tew$|omgq~^#osklmJ#i zSuWYWRBQokuk?#JR;qrn*$ikd{`cdINe)C;a1b5&yps%YtMILAP>{^t26bLITtw%G z#A1X(5m?JVVrta9a>regRars}YI*}Rm*?@eDruxpQjRRu0c1@hl+JN~wUFw#gICF0eE0g zOhn2qNo|93E*HSpMs(tvb{PU0Y!U|WZ?4WN4h4tU>mNN84s!_?(M97mIkl>2Ov%3*maz|tm1ljN3*In~oKTG4C+ z$8e~7R<6eDET#I)7xlgd{_#^xL;=eEAHTBL!-7?ewO^>?$2{4<;Qw|C5JdQ-<>*#1 z5DdB_lDg;I9UokL+}c8U%&(GLy)c%&W*j?^4>a>~LVylyx&?&TggTQ)2oqT6_PEe~ zvInkN#&RX-vkvFVJ+-!FY*zlHo5n@}&?6!8nd)R*18y(TD-T&F19`8YZAOC7if=8L ziJF(TBaMF)&PV>kjhr_;DD2=MDNGiuTlx>RMM)IaC zDK$Y`0GIVTv}E7z?#T{N41w{l+p?r_VNP(f(TT}O$X-ij;$jahz*(9*SF@%7^kg0n z?FYRI^U9&YHy{`j3i{-shtm71ZMtY(4$fTFnL4?&etTp(5#HY>{=+ zab#-1KJ5D7_|nXPHyO;|#)&5Ytl-8Hh}||}TTa5Owf?(U7sT%c{63y;8*9IZ1*yfc z&K>M4Jw#HS4olAFuk^Q#-l7ag{x@E18U9_ot8fI?cB?ujoEnF~4rhMvc^&9em+%Zz zp{@*ASKwbNMboy~9)v7O@teczM!wmJ989nLPFg00pIaRM@jV~~+*xfJ*oBw>u5n{w zO+Fsjh6_aUL(js3?mOO5ev3abD_=nkN(LLJP)<7koBdC6jkW6AjGS#M(9Fj~AB?ym zB-S2sm9rXr;%)dljklBVEzL;0lQb;_*^T8kd0iV};x zm5S@K*Qf=u((&eeYm$yQXd}i5+6_ijq{%m{%d$jqzqP*~=WV z6e~4qa9zxcKRNx$+9>h>Ia2*}zDA{uxCRt=1T}7$5Dh&!kYh<@?>E^}T?fll#>{Rxa_Rct zv5QtZXV57r#1|ctC{9G|)*p_v4f{kN*H#%f9CaX~^9AgRuGeIie*lglQW{Sa7xg^?`A8O74Pl zpCT3X_Zo#E?m7&iYxUQH_heJ>-na8ftX(m1xrBmxqqrS&WnNnb(}UH4tWjN}A0I>% z-i~NL#q%Y<1R|NOL77l1J&Qctt8*@GY9;~X;fqf+ywJcSEmy!rM$H|Koa0}OkI`u% zxq+Un@W+Upf}RO%7s{c~nEWrV;#vh!`U%%CZN?v+KuS>>bYd~SOW3-mu)<(<@Sts# zFsth%XSBZh82MC#P1e9E8MW@{_nES4$ld?;lK zMw;TnHXQ*i3NoPOa|M-MM)q~kce{4>ER9Ioza3oCFF6qV+xI7^dp37eRn_UQTLm?Z zX=gSr{FQU=>~sqhYH&RA(LvE4OLc~z^*J8&Rh&ZNvF4$w6xG+Qu2iA9AvL%NQai`4 zf4WX}!SzFS0#FhuN-kWJ`-u@UgSRFk2nMfdtcyTG)UR=^vc@)VN03hb*^3ed%WX8q z)tN=}t#N@v4Hb<5X?5|f#{H`=#Ip!rk^XcITA@5`(;LP{8i9cS3H_Xh3AbK3lt*eV zkB|w|Z<$yLJc61%$QtavI>T{pA}!`?U$^Jo(;*yVe|J<5kLM?n$J$=3H*+`G-Vstu zOD5p#+AT;hY8VvIz~ z5)cj>yZG7dI8b<%|2kHIz3oEvBLiFPigH6DGa#i z6SO(@Zr6;&P8WQ&nd@V6&@A+MF=%F69eXgRB1mEiQOzE!X{JY`je@bgPl=fg_+$6G zwWwS^UB|AaA(w%oFy~E;)9TDoR^Mr^3CemJTcvKzFvzz&P zBrJW7?%!w-tQNF^^qf#svyEmYs4t*pMX3+4+IW?hSXloY3U0{QCl4ofbH8?|H@K?v zbbh`{AK$cD?HXB{LF_~sr{2$yHvz5u;on=fgAd=6L8WLu-x^t}O}WK02pwsw@(e%O zI0j(NHoARUVT)s8XwU@STOcX_lTx8V$7rYI{y|wEB2%cHt5b`(4#T`_83#z5>G)Xq zw6Y20Q~ft<5kprK{iA$(D%WQ1O!x>wDvsYa7wwx7wI5s+8Nwda5u9e0zM5KKxHcsR zI2YpCnzhj=D4p>p-85*|O8Dd#2WkpuM`RnTOboK0TiUWa7s>h`jdg5Z>BCeY7J{LX zY?Vlt#!8Y3zbp$l>@)^&WB~sSY6XED%Hk80*C|NJl36_4k+(?*?!Q41Mc+38sX1Q|@eb6M7AyMtLC#E}s0|d|5 z*P@J-Ii~SlfB8zEQ!9`)(_+PqibVH&s>u(dwo?qJB1vNnlbcFZIpDhpOqi??IIKU4 zQuPFxl}mead}FhM&0SH9q{l6!uZj_s2W z@HmOfNxpb;(f@`~iG^~@+%9mInvx{UjV zk*cr&yyvW7WUI&Qz|jR?JX2#p$ZNj6$@R=+JKkjOOnBcr8?r&oh*IVV-v6J=oJ_ddE=J3A{4gG;t!gi;&p_LQYm7n?^ zTM0cA{{JPUnP*>)nrul*G$&+v_FZ?R4)bG=nhr!!Udk9LOF%52RYfd^D$6JYqcGa@ z1@XlMbg^N&g~hn<$Av>t^}T+e#XqwkC;i6xhJP$jP4DIJ&TJWo??_=t5`*tZ1QOY) zg?i6E9&DHGKimVE(#9BS7fp%>t%2k#Ifu;D(y;V2FdjMi;u_f>1@gm=g#|X3c1>O? ze#eH6Lbi|b9!8L9#=X2k6l)xtxFE6c#+ki*OfWOk5d(Np%|c)vyG` z21Q(%uDH~gcC#*DBr9$nmPh&#%Q)?^U7;?Fp(W1d2Nb{*OT8Td!cpxD5b%Zd34!t_Kdy_lNi+zl61LGH9;kj@rR zy!|sA<42M8Pwo$74a@9C=U$Br@DuQEMK``Oc-uwp>;sh{|D9?CbmO2mRonV8sw`lh zmu9UXEUw8(>%uTESuL?f%hUogOo0<8uJPNC2F%33tSULW-bi)uS!ma>`shJ+fpu{U zS`a!T_9e=9U$k{$x$(sLYOK%W0G;>0nvNTas@#Vl+NcSth&`%onrjLKf~J7@f6PK2 z%)x^I;@AC{NbBeQo$+mWpnHwk@IFc$i*t>d!uUJZ$dXB_;6VTtQenuzGm!FW{9o-= ziVKfGTwXNCeLvWf5*u=#2*zWkG*YrkDt>xVW^qH>JGH9vgRm#SiGI~#itxt5wfKgj zcpNE)fjeH17VnLnhvcqpvcxz(m0PTE4^1`eB_SA=wc<;7SlJL2f-R z5Pg)yb_&aSI!zXKZ_GloH(r*{*_kIp##dyrJh??@iuEe8F=^~(yBxAu79{9Eze!|d z=`rfXYpsvmQc(7ThsV^yzhQ?EJsOQ6iu#{6Jugp)h2;0M1Hu=!O@LV8TII)y*<${R zT6W?v%{84%|5W~fgoU{MGtb!2@9o7{_h;E&9u{*UXhnR=ea1IIxuu$b(^MI)Ur5Fv z$DwWoh2L_mY2+KYWp$AY%k@F~?lk#tJQPa?qY)3wPP&qAcu2F*HSro}B41LBPTN{VB@7JnPOq_&@fE zx!=E2p{e3b=z+~ZDUyUP%`S+m``JXG>lXy1+V~#97SNs(#a(wrr)GQUj%2U13S}ow z7q$)FTGU%vwl5jh{liJv0->t0jZ~I&mm}G*&%S`-N*_f~qXK)^pe_r$!ZEIe}-ip6E;upwX zJZov#rECoAW`Q?jaxXx@5@8v1Hg#(zyV~l@GDLQ5bytzOXX3K>;}4clyeEk6*X?UG z{X-wVSwhZ!o)Z80cRF+w!>yXwkk{~1r7b@G+UtD6450ZIPJTX!YKaxHNb3CFl6yKI zP{Y&*hc8wB9ZmC?TvvxyM7Pjm^7bF8`2S-Vn#zMFZ?mWe)T zP{Jo@Wlo0rI=Z8XoyCwDDemNV)EjXLSe&;N6J)eLHhg5AF2?bus0vZTT^th~)L$o{ zEK6U84Xc1cE&$@Njfb}2K}UAVAU-(wC^iQP0ELZ( zhE5Yk9?lr)L<*S?9x&(KDxj21TYJ*F5v~?VTGa98OdP7_8MU8}tFgvIcC<4q2n{Wv zoLY3a3tSQUbqjJ0Dy8{h)AOKUojHze$r+&2wV?!RRT^lqLC04Eh)s2+e|n%TZy-F( zfXTz1ly6;UaZ@7bm>Dh%oe`<&{ThRvrTsh!%HFxU4*1kD28#9oQtcgFuM*fdF~_I* zk}vuAW%}%k0rjC_ZthBZ`|sPMIo9c_qJh0&RBWkzvdIhRcDl0V%M-%#nVEAS?e57~ zmT1;3nZw^5M=>uIJMxR1T5m}{<83$qP|>~LN&30OOToW84}G0j^gSxHnUN<(AbWF0 zi=}@JdSWiu`!U`BE?mngJJKLteYE+iK}L94Pal!QoKg#J(k4$}xvpr+0xI+65~cd| zfm6JxWL;g1R#c4io6_zM_ZzFzSH#pMG@=AT$vh;L6(OS~+y=w}@~>Fyt;joYV5T_< z-z1K;H6VYGzdbS#W@ohT%t&8iY*M&G6w%4= zN!YJy-n=Uv%yJjaO_{@~ISP#l)5#PiAyRTy+#<$edOvEdH{}dVK9Je`IXJ6VQ>z0h z{C0+VOTR*utptLktyedziLv9FwOE(MV@`WSjatbis%?MVdSd3eScAt6(CUI~)n^!8 z+6xxw)Tr+}XlMV)v~lDAZdTi4V=;%=W2+lDOwK~k%YxaueP|U}W#Q$q>px5B&ELr= z_7bMDB87x^XYBA*8w%(kS7o?A-<+h1WSf(B^s*MM(ae3}|7TM?{5f;|uVoaD^7%Zs zCKt%dx?lC~SP<{S`_6j>*gaCoL#P@FhC1Kxq(purIZ-Yv+e;D@1g`FoBJ)qU8|sog zjfelG&9{Hm3S?K2GbC^OcSikLg8qY_>jK-9QK{%Zu$EN@!v8&o5ejG9#v=qCXkw{e z(jK6Y*rwGOYIGUy5-*U;xK?D_%SCLM z17Cmc5Sy{h)v`?0qG{DMMtIU`)PvRnH&{kkLxd-Vuds*r`y zyuo*4!VHgAh1;IX$#*+7^hP6-O{^1_8E?>PyD4pNZfV*;=Qw78^l(f3EAfNM?sn(O zU-+hMUNbTD<~;1wcU|_ZWk%3!U8wu(K;M;vBsIATT=#jYF#38ghQ+qOwtKLkfae@P zoq*n#EBe=MeU+lWTv|8Y9*`5Tg3gI9ocM_~R>_CIXE< zWQT;;->X5{mW>iad!f}>@T7?7UU)g^JM^d-0ymG;O)&fN0@kPDVSDxBBwg3i(6Z)n zA9Qzgi9f@Ef-WRnryL`N&IT5n@~K}J)t4O;5yBIoF%l$S7JV6;v4WN1YQm7AIb6({ zs#*vAPdk#;G-!q(%7lPZ*_%&M-glu4=^yc0XrPShyNve<-QGsh`F~?A>z?R>s#Hj;sajy*^ATHC~%90{@nN5;xd+syo-XVB=lZJ&E zFw~2l9*r4C?{NPoDCrbGC-iEux7T?0t@n!?{qh3{zouiOgMK%hc&1OqtG2X6hE+HE zx`Ctd*037z{jR3!I8u9z#99h@rl zTy;v9Z5l{m(D}ar;tL)0)MpL6tZY-eQHgp|9VP*r#F6GmBGIBxyere|ev+15w^CH8 zqxf;_h+6H+&C?C@cfDy@v)a_(RqNIfk*(X%Pk+sGLVe^`)u>j}ZQmWg1MXHAzBxGc z>rLu;*e5}DV*@$$VkNkp*p+L|{oUS(W2lIKyQQ57Y)lp0Yvhz`GYfT1oxFMS;de?W z)yQh3^1mhd`Y*?R$@HoT6Gi9>qfIDy4OEr_zZ0V@#=Qof0*?7apOjC3lOEq$&(pq8*??$kk3(=^+ zu_&9eSkBy{SW(w);KF8(U#wJ-Cxv*O{u$N#nl&S!Ox8HM-M!(LzEUeaOzECT8y~5J zFBLEH!PsO}a@A&AX8?ll*y^*z6%22`e195&pS0!t9J46hO}3sF+sDf`ZOvFjb1X zRyJQhJie-)Tt1&$?O?0Y`X!`dNUVVPiK+fVBYCj^)L!P7S3~+5BBA&*FvpK)vsE6?E*r=e&x|`Q+aH(8Q?9rewjhIlaH0YuNLD{1#ee&#hSX0t zw1ap`W}^`CPA+ z;dCyvrfGB!Ia0+@*l|YYMtZ3gwMWI{BppI@P$+W$v}&QSRAgHn@^PZ;Swptk4V_;4 z7)f$Y@t=I*D))3SOC3P7?)%!BanQ+u)BvDdoCO`;y+2HY!$SfKxPNGKsXtRjmlq;D zIs#zIlepJd{_)%Ak7XS=sip#j(`hLG0`stV)G6{A)=}=cVQdV{I7TQy4ZvS))<1;W zc+K3crS#T*WAbGy%bZl6q7JTn)REdz{6oxXawK4DYUZhuzHQNxnsQyp<1jwfv3B?! zSh(?(MT6j5QJ?5q!hZ&S=7;g3dzcq6ye-@bTcxc>D-HZV;urSi4qtXqK?|$FgR-SG~NG0AAgSg1jP@yXwxdMMA?0S z@#&PyALpXT79YgBd?w$80Ffw0>KJd2y!PE&Bc&xJ6Jc=LycW~G#pT9gu7g4x3hl(t z9SeDl?N$cSII>ZFWW&nHoIdB!=@d`*F`W;aof8L@;Y#L%6ZrOMc@BaSfo%K_eT!_c zMrz*>H}c0h6@LeJFv?zVXGiSZ3Bo)0-cg_8EwSAk(H$hO)Y!k=KX3Fa)~9;g7%Ap9eaDwT43O4j{5NL)XAd29l{7v)W16{3S zsDHg)5U2wJl;J+^XPP#CQP1IJVz34qG@_EM zCITIBS)wGf=MFJrVLOXZKLTNXro`^(6#e_R&wtgCRVQ9Oe81)9z9%a%^^+hC{zp+D zww9Kj$35r}?peOaU(YSNlN8fnwkk02G9?6^B%Li#?7>{US~+}R*w;5V{v)5Ou09~Y zKZ_SK_*j`OJ>lfs+p{kw-EMzRTzI0GsW5ev?F8zk6f0^ZeOF=yV+3su!PFm#3mJon zuYcsQSUdy13P-)33>e*8=5U+IFF8F_anSC~@V|*S>iF8+fv##JaId^{J5!OJtSzCv z!2L{4VHZyE`i2i2bPeOy;j4rH=VT3Zo^wxYX_Z)HtgC-+S&^n^jR!wFd`JL_Q0fw> z*_|e3fEQ=CnkCYy$k{8mOrPN0xpLM3-G8}wp2HX%Nhk`pvGntKgBnc3&9A^%fv!wd z64*K1{P@>9iYKVr54~^vwMz8%M6FW=iU_@-29_~Zc;wDxYE}Mz#Dn>dc8C(}Hm%TE}7AJAO{|IrdNLMn>V<(N_+VT;R1OGy)RdJqu zq(YdCA1~oIqYbw0bZwX=j-oR``Bq=!@<8Y_C}J>hJToy3cNQ7qufQ~Z#A{$%uk+am&6V#%VL8m!e&Q5aCwHT^3=L{7t}n1`C8Db zL{L(mApf9)4zRvj+X&Cuqk%hAGjw){yY6{ZQb$Ez>u?d;$?|{*y)4;zI zq#2T)lVTMagcyAK~e8*PA1ANBx(u#st&%ur*Hz+iyvVKS5P z09D&TROPk}*I=vdT7SIO6PbFni4#|c=udCnxvC8)KYq1>na8=8Q^H5^)8tHXb5=WR z(`sGS{R^Arcmq-O$ji3bZn3@T!?MDEen^T0z=e5VpxBXjIKm^j?6)#J{<#!i+;*Go8sJO7a_!M7{3W7>i4&LRaR7(jnFJA5*oPTz}fAWe^6|H%tVsAgt99Ilst z%DTcxtfZ-%?S|oSPn@s8$hqr``LY;y=3NJKvnb=ST-)IIHw!THTAex{-hcY+_;cV2 zn)cM9`;Y$Fy>VXEl|d{=pV3+8)Zxozxps8?t*tA^f4M>-P4VCE-Kq04@CKTJb7Jm1 zU)1XQ^q-&JzYA>UR5P@q585Sf2FnJ2q|F@Epo`h`?93TEzLV-Cp-IA|& zl5-FdXN)=LJ}%TvXO3S4Kz?7z3hYS*;wU%5%3WQ`lXEe!wH)>MI z!(7QUVM-E70H1OtBH(GlBSG@xYFcP63kf43Vi{*CS3JohAX-IC0>YtGq9NgYt0`kL z$`T@D$k5R=Vj&egS6am^)9fith8q|~3CTj1f96Ew^tw3=l=wt85S#+gVX z$|V&D9OP0XW7gpGy-5}Bh^Am{;$ z1p0s);#g#m!^6G~;7lse;}(>TgxrsD*2UuJ9@0tqY&c}Qg( zg_4O-afJ)G3`G)VVZJAQp^8yTiO6t;%ySX4m`0f6ETpgxRX(%~~2_u2W3rSO~6TnkSkI8Y5hP3bF_Tv@5N!eS56= zrF|IDoc)e}gJm^CIT6is5@L`TLxXsV0Ve37fSgcD)A*>I0RO@L1j{`Zil?X*tXm+c z6qtiD$+3R+ASxDo1}zdnqb?Q*4Zpy$yoTmN%+}WMFk%@ducTRs<$~pjnSiF`A%TQ) zzANntgsd0Ky29>%+m6b@Ah8$Kx(o>RN3O7LQ_QT0C~Qy(2{i(ft4vVm{M_$2;2mGU z)M>9q8&ViuveC#naa$;L(7>!f0_hm$#lf4Pl{FHv<9L2CtFT6K68XRzlxUE`-g4wY zq@L;7__vi=T#V0suGB9`$d*2@Usno#pWe?HmX|F#@u{VM!7m@*AYV=Tu>wM6lO^@ayS;T~&?3{y`N?$q_`(@F7KRh3WUb)K$JehmfpLv@;!K^#zHra;<(|1k z`vHCVI>%6dmWVQ_2ly1)wSx+*#}cnM_8FP%182M~CX?-G*VYSoY^39B-@56*x6{J% zbr(#v7tKEwDU{YDGTl6^V@187#reg!h?IAH{#>t_I(7)vMTwdpTWA6tIhyPHPiFJ! z8FnscaX>vI=Uz9;9@X`&E~<^H{uxbskUw+Y&N~c$`ZBrLsT0S?VY&TWZ<4F+(0Gg5 z_Q$IO11xlAY7O)`{?K#3x{sXS6)5x4B-9^ zLZ{H{f|u>7)1v(&9G7QB}_r)`}C;D4FN#5F)P~NV8 zk0uvab@Lq>r25+huL^Bt*)t&)i}%;R;Eb>bNyn1g79$_DnBA6f)Fa>6BX9#PQkVK# znE9X2)1GA>%AY~UgP32k`~FD3urpU(+8Svp_xY=ORjTUW&&|MM0fXMA76!V;v+qx> zGqBxc(3x~P`04%geJqf>)(7n>e?kLT-h)y^L&>q&pwM`*E^ukR6BTNwUsH9s;k z&FiaoJC_zN5>{bKOR9(99p0RDHy;k>A{3XPob?5Xy%SmAq1YdLF>-$w;yqQ3yZ0wp z#rAUI(ADGjJ5IO98Uohwz1tXB)-AXPuY1%Ud1=G5hV#*HeGcw)%5~G}66+;pwzoAn zS6IaLmGjswRyVcy)dX_|D}qe;-!`MvgrA&v*oP`)WR8q%6=JEPN=Mgn)naEDRGaQt w1>HN>o8XR(8MYF>cB(ha4!^j6E*yy8emI^C1g`GlaOX|_2V|7srZW@(0CCGS_y7O^ delta 2174 zcmV-^2!Z$F5#|vGABzYG_4T`v2TlQykybZ`{J@CgjA;AdM~ zs@fE~klg;~*Gs6(D_)j@%kM7u#=Fr)10PoHe7kzXyM3o7=pTH=4afiO$_eb6Z}{xt zIxhLOgqrsS)`x@1L*H&hfk){>3i`Fr0LP?UwJ_Z)y&L?!}X_s zvaT=^D{1OxyJ0xo6X$C%a_%}~zAVO_dDp?*EXsH+*ETr*%>vB4R;SK~_n$sH{v5c1 zraiUj{-b|(Z=6?kWf05JXLQy%b@*~wt{okJYwODKU#?I{Q~bAEJ9T~r-as>OPRyO> zi&|Zu{`1rOcY)2EYKB(yLA&J5VA+6ww3&k%bTONrojGI2cX+C$QW;|@go;NYKo|=M zGp$3KgpqX4ef&^2ompzUXu)I7lT?La#6vEa=ukjC zz!)f^n4%<2Q<bK80-{yKBybK&B^naWx0*60 zqbwmZh727|BNkG@bEQ?xGR>aSWVnG*l#ncBNse;jB#9y!F+syTLaSK@WUGfIX`G2P zqFhpez(Fpx6fCkXW@-8aa0V8C%hIYMoaDKR;w(?X1XM`EjE9hG!bp^4Jl&|ub4nu{ zN1f9gZ3|@@Ny%cJYeX+O;u5x%5!b0A5!d*m;wa5!%n6~1keP~<~ zibcpMBUu#Xf+?1VI_ou9fC@R5bpxX`Csfc#voOo!gs_Oy9AQ$4L^UdZ$%1b!%FW_X z=Pb`Mrt^%-knl9bEF?kzrd^ot$=x_G%3?xN%=Q!mCY8v-kY!RcDPqDAop56{m1!n4 z;}PZ&U}C2XYb1`c5YrwA-Iu;l#VDmjWD%D#&(X&i&5s$&DaZVfDuZk*ILa}gTqi=L zn8+f*TuX%n#YL9ngmi*`H&&z3?YOB$ZR+vI?q~FKU8=wsjiOY@ax6s=MoE%tj3dwE zh%wH&qJkvhk3_vGW^=Qam5Nx4EYp+;kQt3aO$ab5WXKpsEc%hGx1fsEVl7Mq4I!c_ zNog*b#@b3^LIInAP=K<3BXa*@R4Tte-uIiUprRi$u_c%FR(1Hp}7#VwKY79SVk3Y1L6e_NTw#rWLkO8tU_Z0Ym*b*13<>HUmhdD)VG6Q5cd{POV)^3|jtJCL4` zZF#WdW?rH6phYGGcSOD6(7j(inHtaMfvG=rl;?VPzH9*7UN6>E>Y_E9wO;&M(GAq`c$v=lYweV~0>(l&JZ!4^4n0M{|Au z%4}Xe!_EaQ4yb43-0Mc!qq@G;MYU1YKci_6@@LL}+j)mUUnUnjb>jFqEVrNQO>(sz z8gEhC{&;m@fQ8OXt${wrAA0Ur_mT6vA}i~D(8K(g?x(O@?c0P|{ETkUKdW|(_vQJW z=S@0!Sa;oA{>CO%g_t@8&apU-I{vO@5M1%Xe5p)Px}67Yfc0Iu+eUHxU~qUGdGP5r zLW2)~O}!{u2vEKIvT68rfHb^tAD|gr@^S@ujCl}2-c<0e`oc0`ZiDBBu zvyb%V%yiVj$^U`-k;5K;6m9+#l=kem180AKronIi2vD*tEC=B)FBU(5syiO-SE6C#I0r^1+bQvL0MSB18+?3oaY#rx}Da7NgJq+`i#i;)jn%x=p#>XC2k5x9XC zsY`t=%>2*iY0okb<-%*qN&?ZH+XQ`}|eCDpmFG=VoBBfI)9l3jjV0KcDYN}wARO7KXoD z&5w*s^ZM%D&ZUKmgjJZ*lIkINhc_qP&4+`z2*o8RXMI6p??l#jDE7x*jNIRacu!U1 z?)?c?vAvu)boKcCj??Y2hJbZ^?>0u3bqnsna*x_0i#9xKI3Io2=ipAKTsNI*F0o!> zds~BZg+*LnIgj09byJI9O)yumBFKdQZ8J(u_{oWfeW*f4=E%raA(kqtbaX9OEp~=M zwdsyk(5<=N1b1xAu$Az&Q@#1@@QwTD!h!hhhvUgW;MZLo?!3wW0I)+#x-%320H+H? ABLDyZ From 21fb18e5aa1b6e0aae6f1f7a5c9ee31dbe1e945f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 23 Aug 2016 20:25:52 -0700 Subject: [PATCH 153/193] pep257 fixes --- tests/components/device_tracker/test_tplink.py | 4 +--- tests/components/sensor/test_wunderground.py | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/components/device_tracker/test_tplink.py b/tests/components/device_tracker/test_tplink.py index 715d4f3ffde..da6243e6eff 100644 --- a/tests/components/device_tracker/test_tplink.py +++ b/tests/components/device_tracker/test_tplink.py @@ -28,9 +28,7 @@ class TestTplink4DeviceScanner(unittest.TestCase): @requests_mock.mock() def test_get_mac_addresses_from_both_bands(self, m): - """ - Test grabbing the mac addresses from both 2.4 and 5 GHz clients pages. - """ + """Test grabbing the mac addresses from 2.4 and 5 GHz clients pages.""" conf_dict = { CONF_PLATFORM: 'tplink', CONF_HOST: 'fake_host', diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index 2de7da580f9..3aea771012e 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -29,9 +29,9 @@ ICON_URL = 'http://icons.wxug.com/i/c/k/clear.gif' def mocked_requests_get(*args, **kwargs): """Mock requests.get invocations.""" - class MockResponse: """Class to represent a mocked response.""" + def __init__(self, json_data, status_code): """Initialize the mock response class.""" self.json_data = json_data @@ -83,6 +83,7 @@ class TestWundergroundSetup(unittest.TestCase): DEVICES = [] def add_devices(self, devices): + """Mock add devices.""" for device in devices: self.DEVICES.append(device) From 5d4dc713f25de8bc19ef74dd0447306cb624cae0 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Tue, 23 Aug 2016 21:01:31 -0700 Subject: [PATCH 154/193] Append the travel mode to the sensor name for Google Travel Time --- homeassistant/components/sensor/google_travel_time.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/google_travel_time.py b/homeassistant/components/sensor/google_travel_time.py index 18a97b12910..98cfb469faa 100644 --- a/homeassistant/components/sensor/google_travel_time.py +++ b/homeassistant/components/sensor/google_travel_time.py @@ -52,7 +52,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_API_KEY): cv.string, vol.Required(CONF_DESTINATION): cv.string, vol.Required(CONF_ORIGIN): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_TRAVEL_MODE): vol.In(TRAVEL_MODE), vol.Optional(CONF_OPTIONS, default={CONF_MODE: 'driving'}): vol.All( dict, vol.Schema({ @@ -104,7 +104,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): options[CONF_MODE] = travel_mode titled_mode = options.get(CONF_MODE).title() - formatted_name = "Google Travel Time - {}".format(titled_mode) + formatted_name = "{} - {}".format(DEFAULT_NAME, titled_mode) name = config.get(CONF_NAME, formatted_name) api_key = config.get(CONF_API_KEY) origin = config.get(CONF_ORIGIN) From 78b2c87b542eeb1b3969a389dfcd27bd26800a78 Mon Sep 17 00:00:00 2001 From: Robby Grossman Date: Wed, 24 Aug 2016 01:47:53 -0400 Subject: [PATCH 155/193] Implement support for NEST structures. (#2736) * Implement support for NEST structures. * Conform to balloobbot style preferences. * Log to debug level rather than info level. * Use config validation to coerce list format if supplied as string. * Use list comprehension for more succinct code. * Conform to project linting standards. --- homeassistant/components/nest.py | 31 +++++++++++++++++++++++++------ homeassistant/const.py | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index 005add4e634..430b9baa956 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -8,18 +8,22 @@ import logging import socket import voluptuous as vol +import homeassistant.helpers.config_validation as cv -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, CONF_STRUCTURE REQUIREMENTS = ['python-nest==2.9.2'] DOMAIN = 'nest' NEST = None +STRUCTURES_TO_INCLUDE = None + CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): str, - vol.Required(CONF_PASSWORD): str + vol.Required(CONF_PASSWORD): str, + vol.Optional(CONF_STRUCTURE): vol.All(cv.ensure_list, cv.string) }) }, extra=vol.ALLOW_EXTRA) @@ -30,8 +34,12 @@ def devices(): """Generator returning list of devices and their location.""" try: for structure in NEST.structures: - for device in structure.devices: - yield (structure, device) + if structure.name in STRUCTURES_TO_INCLUDE: + for device in structure.devices: + yield (structure, device) + else: + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, STRUCTURES_TO_INCLUDE) except socket.error: _LOGGER.error("Connection error logging into the nest web service.") @@ -40,8 +48,12 @@ def protect_devices(): """Generator returning list of protect devices.""" try: for structure in NEST.structures: - for device in structure.protectdevices: - yield(structure, device) + if structure.name in STRUCTURES_TO_INCLUDE: + for device in structure.protectdevices: + yield(structure, device) + else: + _LOGGER.info("Ignoring structure %s, not in %s", + structure.name, STRUCTURES_TO_INCLUDE) except socket.error: _LOGGER.error("Connection error logging into the nest web service.") @@ -50,6 +62,7 @@ def protect_devices(): def setup(hass, config): """Setup the Nest thermostat component.""" global NEST + global STRUCTURES_TO_INCLUDE conf = config[DOMAIN] username = conf[CONF_USERNAME] @@ -59,4 +72,10 @@ def setup(hass, config): NEST = nest.Nest(username, password) + if CONF_STRUCTURE not in conf: + STRUCTURES_TO_INCLUDE = [s.name for s in NEST.structures] + else: + STRUCTURES_TO_INCLUDE = conf[CONF_STRUCTURE] + + _LOGGER.debug("Structures to include: %s", STRUCTURES_TO_INCLUDE) return True diff --git a/homeassistant/const.py b/homeassistant/const.py index 4ccaa3cf6f7..77c682868d1 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -59,6 +59,7 @@ CONF_SCAN_INTERVAL = 'scan_interval' CONF_SENSOR_CLASS = 'sensor_class' CONF_SSL = 'ssl' CONF_STATE = 'state' +CONF_STRUCTURE = 'structure' CONF_TEMPERATURE_UNIT = 'temperature_unit' CONF_TIME_ZONE = 'time_zone' CONF_TOKEN = 'token' From 52acb2e6f0e68616b5768aa3aa39de2a671521da Mon Sep 17 00:00:00 2001 From: Carter Date: Wed, 24 Aug 2016 01:28:49 -0500 Subject: [PATCH 156/193] adding pull mode and relay time for you garage door (#2896) * adding pull mode and relay time * fixing failing tests * removed unused vars, removed trailing whitespace * removed white space * split line in 2 * removed whitespace and fixed indent * undid line break * Update rpi_gpio.py new line so its not too long * back to no new line * Moved long method to a new line * Moved comment * moved comment to above method * adding required blank line * fixed variables and made them optional misunderstood the logic at first. * removed line for lint and removed vars that were not required * added second blank line for class * added new configs to platform_schema - still have same error on load * changing string to int * added code to covers rpi as well --- homeassistant/components/cover/rpi_gpio.py | 22 +++++++++++++++---- .../components/garage_door/rpi_gpio.py | 22 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/cover/rpi_gpio.py b/homeassistant/components/cover/rpi_gpio.py index f712e1b17cc..6cef5dc08e7 100644 --- a/homeassistant/components/cover/rpi_gpio.py +++ b/homeassistant/components/cover/rpi_gpio.py @@ -16,6 +16,10 @@ from homeassistant.components.cover import CoverDevice import homeassistant.components.rpi_gpio as rpi_gpio import homeassistant.helpers.config_validation as cv +RELAY_TIME = 'relay_time' +STATE_PULL_MODE = 'state_pull_mode' +DEFAULT_PULL_MODE = 'UP' +DEFAULT_RELAY_TIME = .2 DEPENDENCIES = ['rpi_gpio'] _LOGGER = logging.getLogger(__name__) @@ -33,18 +37,24 @@ _COVERS_SCHEMA = vol.All( PLATFORM_SCHEMA = vol.Schema({ 'platform': str, vol.Required('covers'): _COVERS_SCHEMA, + vol.Optional(STATE_PULL_MODE, default=DEFAULT_PULL_MODE): cv.string, + vol.Optional(RELAY_TIME, default=DEFAULT_RELAY_TIME): vol.Coerce(int), }) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the cover platform.""" + relay_time = config.get(RELAY_TIME) + state_pull_mode = config.get(STATE_PULL_MODE) covers = [] covers_conf = config.get('covers') for cover in covers_conf: covers.append(RPiGPIOCover(cover['name'], cover['relay_pin'], - cover['state_pin'])) + cover['state_pin'], + state_pull_mode, + relay_time)) add_devices(covers) @@ -52,14 +62,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class RPiGPIOCover(CoverDevice): """Representation of a Raspberry cover.""" - def __init__(self, name, relay_pin, state_pin): + # pylint: disable=too-many-arguments + def __init__(self, name, relay_pin, state_pin, + state_pull_mode, relay_time): """Initialize the cover.""" self._name = name self._state = False self._relay_pin = relay_pin self._state_pin = state_pin + self._state_pull_mode = state_pull_mode + self._relay_time = relay_time rpi_gpio.setup_output(self._relay_pin) - rpi_gpio.setup_input(self._state_pin, 'UP') + rpi_gpio.setup_input(self._state_pin, self._state_pull_mode) rpi_gpio.write_output(self._relay_pin, True) @property @@ -84,7 +98,7 @@ class RPiGPIOCover(CoverDevice): def _trigger(self): """Trigger the cover.""" rpi_gpio.write_output(self._relay_pin, False) - sleep(0.2) + sleep(self._relay_time) rpi_gpio.write_output(self._relay_pin, True) def close_cover(self): diff --git a/homeassistant/components/garage_door/rpi_gpio.py b/homeassistant/components/garage_door/rpi_gpio.py index 55ade8c9fc0..3969e12371c 100644 --- a/homeassistant/components/garage_door/rpi_gpio.py +++ b/homeassistant/components/garage_door/rpi_gpio.py @@ -15,6 +15,10 @@ from homeassistant.components.garage_door import GarageDoorDevice import homeassistant.components.rpi_gpio as rpi_gpio import homeassistant.helpers.config_validation as cv +RELAY_TIME = 'relay_time' +STATE_PULL_MODE = 'state_pull_mode' +DEFAULT_PULL_MODE = 'UP' +DEFAULT_RELAY_TIME = .2 DEPENDENCIES = ['rpi_gpio'] _LOGGER = logging.getLogger(__name__) @@ -32,32 +36,42 @@ _DOORS_SCHEMA = vol.All( PLATFORM_SCHEMA = vol.Schema({ 'platform': str, vol.Required('doors'): _DOORS_SCHEMA, + vol.Optional(STATE_PULL_MODE, default=DEFAULT_PULL_MODE): cv.string, + vol.Optional(RELAY_TIME, default=DEFAULT_RELAY_TIME): vol.Coerce(int), }) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the garage door platform.""" + relay_time = config.get(RELAY_TIME) + state_pull_mode = config.get(STATE_PULL_MODE) doors = [] doors_conf = config.get('doors') for door in doors_conf: doors.append(RPiGPIOGarageDoor(door['name'], door['relay_pin'], - door['state_pin'])) + door['state_pin'], + state_pull_mode, + relay_time)) add_devices(doors) class RPiGPIOGarageDoor(GarageDoorDevice): """Representation of a Raspberry garage door.""" - def __init__(self, name, relay_pin, state_pin): + # pylint: disable=too-many-arguments + def __init__(self, name, relay_pin, state_pin, + state_pull_mode, relay_time): """Initialize the garage door.""" self._name = name self._state = False self._relay_pin = relay_pin self._state_pin = state_pin + self._state_pull_mode = state_pull_mode + self._relay_time = relay_time rpi_gpio.setup_output(self._relay_pin) - rpi_gpio.setup_input(self._state_pin, 'UP') + rpi_gpio.setup_input(self._state_pin, self._state_pull_mode) rpi_gpio.write_output(self._relay_pin, True) @property @@ -82,7 +96,7 @@ class RPiGPIOGarageDoor(GarageDoorDevice): def _trigger(self): """Trigger the door.""" rpi_gpio.write_output(self._relay_pin, False) - sleep(0.2) + sleep(self._relay_time) rpi_gpio.write_output(self._relay_pin, True) def close_door(self): From 61ef2683c512b010cfdf11b879446922d26307c3 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Wed, 24 Aug 2016 02:32:00 -0400 Subject: [PATCH 157/193] Add volume and seek control to gpmdp (#2953) --- .../components/media_player/gpmdp.py | 125 ++++++++++++------ 1 file changed, 82 insertions(+), 43 deletions(-) diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py index 85f697cb1e7..4fcdff872e2 100644 --- a/homeassistant/components/media_player/gpmdp.py +++ b/homeassistant/components/media_player/gpmdp.py @@ -11,17 +11,22 @@ import socket from homeassistant.components.media_player import ( MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK, - SUPPORT_PAUSE, MediaPlayerDevice) + SUPPORT_PAUSE, SUPPORT_VOLUME_SET, SUPPORT_SEEK, MediaPlayerDevice) from homeassistant.const import ( STATE_PLAYING, STATE_PAUSED, STATE_OFF) from homeassistant.loader import get_component _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['websocket-client==0.37.0'] -SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK +SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \ + SUPPORT_SEEK | SUPPORT_VOLUME_SET GPMDP_CONFIG_FILE = 'gpmpd.conf' _CONFIGURING = {} +PLAYBACK_DICT = {'0': STATE_PAUSED, # Stopped + '1': STATE_PAUSED, + '2': STATE_PLAYING} + def request_configuration(hass, config, url, add_devices_callback): """Request configuration steps from the user.""" @@ -162,6 +167,7 @@ class GPMDP(MediaPlayerDevice): self._albumart = None self._seek_position = None self._duration = None + self._volume = None self._request_id = 0 self.update() @@ -180,7 +186,7 @@ class GPMDP(MediaPlayerDevice): self._ws = None return self._ws - def send_msg_with_req_id(self, method): + def send_gpmdp_msg(self, namespace, method, with_id=True): """Send ws messages to GPMDP and verify request id in response.""" from websocket import _exceptions try: @@ -188,38 +194,42 @@ class GPMDP(MediaPlayerDevice): if websocket is None: self._status = STATE_OFF return - else: - self._request_id += 1 - websocket.send(json.dumps({'namespace': 'playback', - 'method': method, - 'requestID': self._request_id})) - while True: - msg = json.loads(websocket.recv()) - if 'requestID' in msg: - if msg['requestID'] == self._request_id: - return msg - except (_exceptions.WebSocketTimeoutException, + self._request_id += 1 + websocket.send(json.dumps({'namespace': namespace, + 'method': method, + 'requestID': self._request_id})) + if not with_id: + return + while True: + msg = json.loads(websocket.recv()) + if 'requestID' in msg: + if msg['requestID'] == self._request_id: + return msg + except (ConnectionRefusedError, ConnectionResetError, + _exceptions.WebSocketTimeoutException, _exceptions.WebSocketProtocolException, - _exceptions.WebSocketPayloadException): - return + _exceptions.WebSocketPayloadException, + _exceptions.WebSocketConnectionClosedException): + self._ws = None def update(self): """Get the latest details from the player.""" - playstate = self.send_msg_with_req_id('isPlaying') + playstate = self.send_gpmdp_msg('playback', 'getPlaybackState') if playstate is None: return - self._status = STATE_PLAYING if playstate['value'] else STATE_PAUSED - time_data = self.send_msg_with_req_id('getCurrentTime') - if time_data is None: - return - self._seek_position = int(time_data['value'] / 1000) - track_data = self.send_msg_with_req_id('getCurrentTrack') - if track_data is None: - return - self._title = track_data['value']['title'] - self._artist = track_data['value']['artist'] - self._albumart = track_data['value']['albumArt'] - self._duration = int(track_data['value']['duration'] / 1000) + self._status = PLAYBACK_DICT[str(playstate['value'])] + time_data = self.send_gpmdp_msg('playback', 'getCurrentTime') + if time_data is not None: + self._seek_position = int(time_data['value'] / 1000) + track_data = self.send_gpmdp_msg('playback', 'getCurrentTrack') + if track_data is not None: + self._title = track_data['value']['title'] + self._artist = track_data['value']['artist'] + self._albumart = track_data['value']['albumArt'] + self._duration = int(track_data['value']['duration'] / 1000) + volume_data = self.send_gpmdp_msg('volume', 'getVolume') + if volume_data is not None: + self._volume = volume_data['value'] / 100 @property def media_content_type(self): @@ -256,6 +266,11 @@ class GPMDP(MediaPlayerDevice): """Time in seconds of current song duration.""" return self._duration + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume + @property def name(self): """Return the name of the device.""" @@ -268,32 +283,56 @@ class GPMDP(MediaPlayerDevice): def media_next_track(self): """Send media_next command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "forward"}') + self.send_gpmdp_msg('playback', 'forward', False) def media_previous_track(self): """Send media_previous command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "rewind"}') + self.send_gpmdp_msg('playback', 'rewind', False) def media_play(self): """Send media_play command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "playPause"}') + self.send_gpmdp_msg('playback', 'playPause', False) self._status = STATE_PLAYING self.update_ha_state() def media_pause(self): """Send media_pause command to media player.""" + self.send_gpmdp_msg('playback', 'playPause', False) + self._status = STATE_PAUSED + self.update_ha_state() + + def media_seek(self, position): + """Send media_seek command to media player.""" websocket = self.get_ws() if websocket is None: return - websocket.send('{"namespace": "playback", "method": "playPause"}') - self._status = STATE_PAUSED + websocket.send(json.dumps({"namespace": "playback", + "method": "setCurrentTime", + "arguments": [position*1000]})) + self.update_ha_state() + + def volume_up(self): + """Send volume_up command to media player.""" + websocket = self.get_ws() + if websocket is None: + return + websocket.send('{"namespace": "volume", "method": "increaseVolume"}') + self.update_ha_state() + + def volume_down(self): + """Send volume_down command to media player.""" + websocket = self.get_ws() + if websocket is None: + return + websocket.send('{"namespace": "volume", "method": "decreaseVolume"}') + self.update_ha_state() + + def set_volume_level(self, volume): + """Set volume on media player, range(0..1).""" + websocket = self.get_ws() + if websocket is None: + return + websocket.send(json.dumps({"namespace": "volume", + "method": "setVolume", + "arguments": [volume*100]})) self.update_ha_state() From 4795122463c8b775f9dcdb6114c66bda0c69c70e Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Wed, 24 Aug 2016 09:16:26 +0100 Subject: [PATCH 158/193] Add voluptuous to binary template sensor (#2938) * Add voluptuous to binary template sensor / update failing test. * Update tests. * Quick fixes to remove duplicate variables --- .../components/binary_sensor/template.py | 52 +++++++-------- .../components/binary_sensor/test_template.py | 65 ++++++++++++------- 2 files changed, 62 insertions(+), 55 deletions(-) diff --git a/homeassistant/components/binary_sensor/template.py b/homeassistant/components/binary_sensor/template.py index ee68e817275..e87594e625c 100644 --- a/homeassistant/components/binary_sensor/template.py +++ b/homeassistant/components/binary_sensor/template.py @@ -5,55 +5,47 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.template/ """ import logging +import voluptuous as vol +import homeassistant.helpers.config_validation as cv from homeassistant.components.binary_sensor import (BinarySensorDevice, ENTITY_ID_FORMAT, - SENSOR_CLASSES) -from homeassistant.const import (ATTR_FRIENDLY_NAME, CONF_VALUE_TEMPLATE, - ATTR_ENTITY_ID, MATCH_ALL) + PLATFORM_SCHEMA, + SENSOR_CLASSES_SCHEMA) + +from homeassistant.const import (ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, MATCH_ALL, + CONF_VALUE_TEMPLATE, CONF_SENSOR_CLASS) from homeassistant.exceptions import TemplateError from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers import template from homeassistant.helpers.event import track_state_change -from homeassistant.util import slugify CONF_SENSORS = 'sensors' + +SENSOR_SCHEMA = vol.Schema({ + vol.Required(CONF_VALUE_TEMPLATE): cv.template, + vol.Optional(ATTR_FRIENDLY_NAME): cv.string, + vol.Optional(ATTR_ENTITY_ID, default=MATCH_ALL): cv.entity_ids, + vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_SENSORS): vol.Schema({cv.slug: SENSOR_SCHEMA}), +}) + _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup template binary sensors.""" sensors = [] - if config.get(CONF_SENSORS) is None: - _LOGGER.error('Missing configuration data for binary_sensor platform') - return False for device, device_config in config[CONF_SENSORS].items(): - if device != slugify(device): - _LOGGER.error('Found invalid key for binary_sensor.template: %s. ' - 'Use %s instead', device, slugify(device)) - continue - - if not isinstance(device_config, dict): - _LOGGER.error('Missing configuration data for binary_sensor %s', - device) - continue - + value_template = device_config[CONF_VALUE_TEMPLATE] + entity_ids = device_config[ATTR_ENTITY_ID] friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) - sensor_class = device_config.get('sensor_class') - value_template = device_config.get(CONF_VALUE_TEMPLATE) - - if sensor_class not in SENSOR_CLASSES: - _LOGGER.error('Sensor class is not valid') - continue - - if value_template is None: - _LOGGER.error( - 'Missing %s for sensor %s', CONF_VALUE_TEMPLATE, device) - continue - - entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL) + sensor_class = device_config.get(CONF_SENSOR_CLASS) sensors.append( BinarySensorTemplate( diff --git a/tests/components/binary_sensor/test_template.py b/tests/components/binary_sensor/test_template.py index 634834779d5..0f08817f15a 100644 --- a/tests/components/binary_sensor/test_template.py +++ b/tests/components/binary_sensor/test_template.py @@ -3,6 +3,7 @@ import unittest from unittest import mock from homeassistant.const import EVENT_STATE_CHANGED, MATCH_ALL +import homeassistant.bootstrap as bootstrap from homeassistant.components.binary_sensor import template from homeassistant.exceptions import TemplateError @@ -21,6 +22,7 @@ class TestBinarySensorTemplate(unittest.TestCase): 'friendly_name': 'virtual thingy', 'value_template': '{{ foo }}', 'sensor_class': 'motion', + 'entity_id': 'test' }, } } @@ -29,48 +31,61 @@ class TestBinarySensorTemplate(unittest.TestCase): result = template.setup_platform(hass, config, add_devices) self.assertTrue(result) mock_template.assert_called_once_with(hass, 'test', 'virtual thingy', - 'motion', '{{ foo }}', MATCH_ALL) + 'motion', '{{ foo }}', 'test') add_devices.assert_called_once_with([mock_template.return_value]) def test_setup_no_sensors(self): """"Test setup with no sensors.""" - config = {} - result = template.setup_platform(None, config, None) + hass = mock.MagicMock() + result = bootstrap.setup_component(hass, 'sensor', { + 'sensor': { + 'platform': 'template' + } + }) self.assertFalse(result) def test_setup_invalid_device(self): """"Test the setup with invalid devices.""" - config = { - 'sensors': { - 'foo bar': {}, - }, - } - result = template.setup_platform(None, config, None) + hass = mock.MagicMock() + result = bootstrap.setup_component(hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'foo bar': {}, + }, + } + }) self.assertFalse(result) def test_setup_invalid_sensor_class(self): """"Test setup with invalid sensor class.""" - config = { - 'sensors': { - 'test': { - 'value_template': '{{ foo }}', - 'sensor_class': 'foobarnotreal', + hass = mock.MagicMock() + result = bootstrap.setup_component(hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'test': { + 'value_template': '{{ foo }}', + 'sensor_class': 'foobarnotreal', + }, }, - }, - } - result = template.setup_platform(None, config, None) + } + }) self.assertFalse(result) def test_setup_invalid_missing_template(self): """"Test setup with invalid and missing template.""" - config = { - 'sensors': { - 'test': { - 'sensor_class': 'motion', - }, - }, - } - result = template.setup_platform(None, config, None) + hass = mock.MagicMock() + result = bootstrap.setup_component(hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'test': { + 'sensor_class': 'motion', + }, + } + } + }) self.assertFalse(result) def test_attributes(self): From e7b206da0c8d391019e39662d666b99c05b86b81 Mon Sep 17 00:00:00 2001 From: MartinHjelmare Date: Thu, 14 Jul 2016 02:44:46 +0200 Subject: [PATCH 159/193] Add MQTT gateway for MySensors * Use mqtt component to enable a MySensors MQTT gateway. * Setup the MQTT gateway if mysensors config has mqtt as a value for the key device in the list of gateways. * Simplify two lines in the mqtt component. --- homeassistant/components/mqtt/__init__.py | 4 +- homeassistant/components/mysensors.py | 84 +++++++++++++++-------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 6db231f6bd7..e06f60b6e1a 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -203,14 +203,14 @@ def setup(hass, config): broker_config = _setup_server(hass, config) - broker_in_conf = True if CONF_BROKER in conf else False + broker_in_conf = CONF_BROKER in conf # Only auto config if no server config was passed in if broker_config and CONF_EMBEDDED not in conf: broker, port, username, password, certificate, protocol = broker_config # Embedded broker doesn't have some ssl variables client_key, client_cert, tls_insecure = None, None, None - elif not broker_config and CONF_BROKER not in conf: + elif not broker_config and not broker_in_conf: _LOGGER.error('Unable to start broker and auto-configure MQTT.') return False diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index d40806bdc31..8a53bc011cd 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -7,11 +7,12 @@ https://home-assistant.io/components/sensor.mysensors/ import logging import socket +from homeassistant.bootstrap import setup_component from homeassistant.const import (ATTR_BATTERY_LEVEL, CONF_OPTIMISTIC, EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP, - STATE_OFF, STATE_ON) -from homeassistant.helpers import validate_config, discovery + EVENT_HOMEASSISTANT_STOP, STATE_OFF, STATE_ON) +from homeassistant.helpers import discovery, validate_config +from homeassistant.loader import get_component CONF_GATEWAYS = 'gateways' CONF_DEVICE = 'device' @@ -21,6 +22,9 @@ CONF_PERSISTENCE_FILE = 'persistence_file' CONF_VERSION = 'version' CONF_BAUD_RATE = 'baud_rate' CONF_TCP_PORT = 'tcp_port' +CONF_TOPIC_IN_PREFIX = 'topic_in_prefix' +CONF_TOPIC_OUT_PREFIX = 'topic_out_prefix' +CONF_RETAIN = 'retain' DEFAULT_VERSION = '1.4' DEFAULT_BAUD_RATE = 115200 DEFAULT_TCP_PORT = 5003 @@ -56,25 +60,47 @@ def setup(hass, config): # pylint: disable=too-many-locals is_metric = hass.config.units.is_metric persistence = config[DOMAIN].get(CONF_PERSISTENCE, True) - def setup_gateway(device, persistence_file, baud_rate, tcp_port): + def setup_gateway(device, persistence_file, baud_rate, tcp_port, in_prefix, + out_prefix): """Return gateway after setup of the gateway.""" - try: - socket.inet_aton(device) - # valid ip address - gateway = mysensors.TCPGateway( - device, event_callback=None, persistence=persistence, - persistence_file=persistence_file, protocol_version=version, - port=tcp_port) - except OSError: - # invalid ip address - gateway = mysensors.SerialGateway( - device, event_callback=None, persistence=persistence, - persistence_file=persistence_file, protocol_version=version, - baud=baud_rate) + # pylint: disable=too-many-arguments + if device in 'mqtt': + if not setup_component(hass, 'mqtt', config): + return + mqtt = get_component('mqtt') + retain = config[DOMAIN].get(CONF_RETAIN, True) + + def pub_callback(topic, payload, qos, retain): + """Call mqtt publish function.""" + mqtt.publish(hass, topic, payload, qos, retain) + + def sub_callback(topic, callback, qos): + """Call mqtt subscribe function.""" + mqtt.subscribe(hass, topic, callback, qos) + gateway = mysensors.MQTTGateway( + pub_callback, sub_callback, + event_callback=None, persistence=persistence, + persistence_file=persistence_file, + protocol_version=version, in_prefix=in_prefix, + out_prefix=out_prefix, retain=retain) + else: + try: + socket.inet_aton(device) + # valid ip address + gateway = mysensors.TCPGateway( + device, event_callback=None, persistence=persistence, + persistence_file=persistence_file, + protocol_version=version, port=tcp_port) + except OSError: + # invalid ip address + gateway = mysensors.SerialGateway( + device, event_callback=None, persistence=persistence, + persistence_file=persistence_file, + protocol_version=version, baud=baud_rate) gateway.metric = is_metric gateway.debug = config[DOMAIN].get(CONF_DEBUG, False) optimistic = config[DOMAIN].get(CONF_OPTIMISTIC, False) - gateway = GatewayWrapper(gateway, version, optimistic) + gateway = GatewayWrapper(gateway, version, optimistic, device) # pylint: disable=attribute-defined-outside-init gateway.event_callback = gateway.callback_factory() @@ -105,8 +131,13 @@ def setup(hass, config): # pylint: disable=too-many-locals hass.config.path('mysensors{}.pickle'.format(index + 1))) baud_rate = gway.get(CONF_BAUD_RATE, DEFAULT_BAUD_RATE) tcp_port = gway.get(CONF_TCP_PORT, DEFAULT_TCP_PORT) + in_prefix = gway.get(CONF_TOPIC_IN_PREFIX, '') + out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX, '') GATEWAYS[device] = setup_gateway( - device, persistence_file, baud_rate, tcp_port) + device, persistence_file, baud_rate, tcp_port, in_prefix, + out_prefix) + if GATEWAYS[device] is None: + GATEWAYS.pop(device) for component in 'sensor', 'switch', 'light', 'binary_sensor': discovery.load_platform(hass, component, DOMAIN, {}, config) @@ -152,16 +183,17 @@ class GatewayWrapper(object): # pylint: disable=too-few-public-methods - def __init__(self, gateway, version, optimistic): + def __init__(self, gateway, version, optimistic, device): """Setup class attributes on instantiation. Args: - gateway (mysensors.SerialGateway): Gateway to wrap. + gateway (mysensors.Gateway): Gateway to wrap. version (str): Version of mysensors API. optimistic (bool): Send values to actuators without feedback state. + device (str): Path to serial port, ip adress or mqtt. Attributes: - _wrapped_gateway (mysensors.SerialGateway): Wrapped gateway. + _wrapped_gateway (mysensors.Gateway): Wrapped gateway. version (str): Version of mysensors API. platform_callbacks (list): Callback functions, one per platform. optimistic (bool): Send values to actuators without feedback state. @@ -171,6 +203,7 @@ class GatewayWrapper(object): self.version = version self.platform_callbacks = [] self.optimistic = optimistic + self.device = device self.__initialised = True def __getattr__(self, name): @@ -253,13 +286,8 @@ class MySensorsDeviceEntity(object): @property def device_state_attributes(self): """Return device specific state attributes.""" - address = getattr(self.gateway, 'server_address', None) - if address: - device = '{}:{}'.format(address[0], address[1]) - else: - device = self.gateway.port attr = { - ATTR_DEVICE: device, + ATTR_DEVICE: self.gateway.device, ATTR_NODE_ID: self.node_id, ATTR_CHILD_ID: self.child_id, ATTR_BATTERY_LEVEL: self.battery_level, From 99796e559e9fbea7b4db03c992e09fd1e978c1bf Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 24 Aug 2016 11:02:40 +0200 Subject: [PATCH 160/193] minor bug in rfxtrx sensor --- homeassistant/components/sensor/rfxtrx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/rfxtrx.py b/homeassistant/components/sensor/rfxtrx.py index 7560adbc93a..67aff8956d3 100644 --- a/homeassistant/components/sensor/rfxtrx.py +++ b/homeassistant/components/sensor/rfxtrx.py @@ -41,7 +41,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): sub_sensors = {} data_types = entity_info[ATTR_DATA_TYPE] if len(data_types) == 0: - data_type = "Unknown" + data_types = ["Unknown"] for data_type in DATA_TYPES: if data_type in event.values: data_types = [data_type] @@ -121,7 +121,7 @@ class RfxtrxSensor(Entity): @property def state(self): """Return the state of the sensor.""" - if self.event: + if self.event and self.data_type in self.event.values: return self.event.values[self.data_type] return None From e5abf6074cf0cad89be76343bbe27b43d8af5cc4 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Wed, 24 Aug 2016 11:53:02 +0200 Subject: [PATCH 161/193] Cover (#2957) * current_position was set, it should be optional * Update mqtt test to match --- homeassistant/components/cover/__init__.py | 12 +++++++----- tests/components/cover/test_mqtt.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index 0c74ea4eb31..b4b73d0e462 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -163,7 +163,7 @@ class CoverDevice(Entity): None is unknown, 0 is closed, 100 is fully open. """ - return None + pass @property def current_cover_tilt_position(self): @@ -171,7 +171,7 @@ class CoverDevice(Entity): None is unknown, 0 is closed, 100 is fully open. """ - return None + pass @property def state(self): @@ -186,9 +186,11 @@ class CoverDevice(Entity): @property def state_attributes(self): """Return the state attributes.""" - data = { - ATTR_CURRENT_POSITION: self.current_cover_position - } + data = {} + + current = self.current_cover_position + if current is not None: + data[ATTR_CURRENT_POSITION] = self.current_cover_position current_tilt = self.current_cover_tilt_position if current_tilt is not None: diff --git a/tests/components/cover/test_mqtt.py b/tests/components/cover/test_mqtt.py index a1b9f0b92fc..e2bc008f3d7 100644 --- a/tests/components/cover/test_mqtt.py +++ b/tests/components/cover/test_mqtt.py @@ -147,7 +147,7 @@ class TestCoverMQTT(unittest.TestCase): state_attributes_dict = self.hass.states.get( 'cover.test').attributes - self.assertTrue('current_position' in state_attributes_dict) + self.assertFalse('current_position' in state_attributes_dict) fire_mqtt_message(self.hass, 'state-topic', '0') self.hass.pool.block_till_done() From 5d2d9af8e39f9fcc1c220b362b49a2df2b82437b Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Wed, 24 Aug 2016 16:30:14 +0200 Subject: [PATCH 162/193] Add deprecated warning to thermostat and hvac (#2962) * Add deprecated warning for thermostat and hvac --- homeassistant/components/hvac/__init__.py | 3 +++ homeassistant/components/thermostat/__init__.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/homeassistant/components/hvac/__init__.py b/homeassistant/components/hvac/__init__.py index abd40a3ac93..ab27af480a7 100644 --- a/homeassistant/components/hvac/__init__.py +++ b/homeassistant/components/hvac/__init__.py @@ -135,6 +135,9 @@ def set_swing_mode(hass, swing_mode, entity_id=None): # pylint: disable=too-many-branches def setup(hass, config): """Setup hvacs.""" + _LOGGER.warning('This component has been deprecated in favour of' + ' the "climate" component and will be removed ' + 'in the future. Please upgrade.') component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) component.setup(config) diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py index 09a18b91402..a9169ce4756 100644 --- a/homeassistant/components/thermostat/__init__.py +++ b/homeassistant/components/thermostat/__init__.py @@ -115,6 +115,9 @@ def set_hvac_mode(hass, hvac_mode, entity_id=None): # pylint: disable=too-many-branches def setup(hass, config): """Setup thermostats.""" + _LOGGER.warning('This component has been deprecated in favour of' + ' the "climate" component and will be removed ' + 'in the future. Please upgrade.') component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) component.setup(config) From cc358a5ddefd263518f94cad36c65fae869644d2 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Wed, 24 Aug 2016 18:54:34 +0200 Subject: [PATCH 163/193] Corrected sensor name from HM-Z19 to MH-Z19 (#2963) Approved --- .coveragerc | 2 +- homeassistant/components/sensor/{hmz19.py => mhz19.py} | 6 +++--- requirements_all.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename homeassistant/components/sensor/{hmz19.py => mhz19.py} (94%) diff --git a/.coveragerc b/.coveragerc index e6b268ed38b..48ea0375587 100644 --- a/.coveragerc +++ b/.coveragerc @@ -220,11 +220,11 @@ omit = homeassistant/components/sensor/google_travel_time.py homeassistant/components/sensor/gpsd.py homeassistant/components/sensor/gtfs.py - homeassistant/components/sensor/hmz19.py homeassistant/components/sensor/hp_ilo.py homeassistant/components/sensor/imap.py homeassistant/components/sensor/lastfm.py homeassistant/components/sensor/loopenergy.py + homeassistant/components/sensor/mhz19.py homeassistant/components/sensor/mqtt_room.py homeassistant/components/sensor/neurio_energy.py homeassistant/components/sensor/nzbget.py diff --git a/homeassistant/components/sensor/hmz19.py b/homeassistant/components/sensor/mhz19.py similarity index 94% rename from homeassistant/components/sensor/hmz19.py rename to homeassistant/components/sensor/mhz19.py index 9cf3e4e4dd2..c811a193335 100644 --- a/homeassistant/components/sensor/hmz19.py +++ b/homeassistant/components/sensor/mhz19.py @@ -2,7 +2,7 @@ Support for CO2 sensor connected to a serial port. For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.hmz19/ +https://home-assistant.io/components/sensor.mhz19/ """ import logging import voluptuous as vol @@ -37,11 +37,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get(CONF_SERIAL_DEVICE), err) return False - dev = HMZ19Sensor(config.get(CONF_SERIAL_DEVICE), config.get(CONF_NAME)) + dev = MHZ19Sensor(config.get(CONF_SERIAL_DEVICE), config.get(CONF_NAME)) add_devices([dev]) -class HMZ19Sensor(Entity): +class MHZ19Sensor(Entity): """Representation of an CO2 sensor.""" def __init__(self, serial_device, name): diff --git a/requirements_all.txt b/requirements_all.txt index af472e31cca..e9d125d764a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -261,7 +261,7 @@ pilight==0.0.2 # homeassistant.components.sensor.plex plexapi==2.0.2 -# homeassistant.components.sensor.hmz19 +# homeassistant.components.sensor.mhz19 # homeassistant.components.sensor.serial_pm pmsensor==0.3 From d9322b81f379d5476a6ffb056f9f83437aee5e58 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Wed, 24 Aug 2016 20:36:43 +0200 Subject: [PATCH 164/193] Bugfixing DemoCover NotImplemented Was not raised for is_closed (#2965) * NotImplemented was not raised when is_closed was missing * Bugfixing Demo --- homeassistant/components/cover/__init__.py | 2 +- homeassistant/components/cover/demo.py | 26 ++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index b4b73d0e462..3f08c7ff229 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -201,7 +201,7 @@ class CoverDevice(Entity): @property def is_closed(self): """Return if the cover is closed or not.""" - return NotImplementedError() + raise NotImplementedError() def open_cover(self, **kwargs): """Open the cover.""" diff --git a/homeassistant/components/cover/demo.py b/homeassistant/components/cover/demo.py index a863ad83a64..1f1c666f339 100644 --- a/homeassistant/components/cover/demo.py +++ b/homeassistant/components/cover/demo.py @@ -55,9 +55,20 @@ class DemoCover(CoverDevice): """Return the current tilt position of the cover.""" return self._tilt_position + @property + def is_closed(self): + """Return if the cover is closed.""" + if self._position is not None: + if self.current_cover_position > 0: + return False + else: + return True + else: + return None + def close_cover(self, **kwargs): """Close the cover.""" - if self._position == 0: + if self._position in (0, None): return self._listen_cover() @@ -65,7 +76,7 @@ class DemoCover(CoverDevice): def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" - if self._tilt_position == 0: + if self._tilt_position in (0, None): return self._listen_cover_tilt() @@ -73,7 +84,7 @@ class DemoCover(CoverDevice): def open_cover(self, **kwargs): """Open the cover.""" - if self._position == 100: + if self._position in (100, None): return self._listen_cover() @@ -81,7 +92,7 @@ class DemoCover(CoverDevice): def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" - if self._tilt_position == 100: + if self._tilt_position in (100, None): return self._listen_cover_tilt() @@ -92,6 +103,7 @@ class DemoCover(CoverDevice): self._set_position = round(position, -1) if self._position == position: return + self._listen_cover() self._closing = position < self._position @@ -100,11 +112,14 @@ class DemoCover(CoverDevice): self._set_tilt_position = round(tilt_position, -1) if self._tilt_position == tilt_position: return + self._listen_cover_tilt() self._closing_tilt = tilt_position < self._tilt_position def stop_cover(self, **kwargs): """Stop the cover.""" + if self._position is None: + return if self._listener_cover is not None: self.hass.bus.remove_listener(EVENT_TIME_CHANGED, self._listener_cover) @@ -113,6 +128,9 @@ class DemoCover(CoverDevice): def stop_cover_tilt(self, **kwargs): """Stop the cover tilt.""" + if self._tilt_position is None: + return + if self._listener_cover_tilt is not None: self.hass.bus.remove_listener(EVENT_TIME_CHANGED, self._listener_cover_tilt) From 9219d65c3e03cf6f6c3af37a9d1f06c8b6db5160 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 25 Aug 2016 06:35:09 +0200 Subject: [PATCH 165/193] Migrate to voluptuous (#2958) --- .../components/binary_sensor/enocean.py | 36 ++++++++++++++----- homeassistant/components/enocean.py | 19 ++++++++-- homeassistant/components/light/enocean.py | 29 +++++++++------ homeassistant/components/sensor/enocean.py | 22 +++++++++--- homeassistant/components/switch/enocean.py | 20 +++++++---- homeassistant/const.py | 2 ++ 6 files changed, 94 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/binary_sensor/enocean.py b/homeassistant/components/binary_sensor/enocean.py index 12f073f9e85..631ed0021e1 100644 --- a/homeassistant/components/binary_sensor/enocean.py +++ b/homeassistant/components/binary_sensor/enocean.py @@ -4,27 +4,41 @@ Support for EnOcean binary sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.enocean/ """ +import logging -from homeassistant.components.binary_sensor import BinarySensorDevice +import voluptuous as vol + +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) from homeassistant.components import enocean -from homeassistant.const import CONF_NAME +from homeassistant.const import (CONF_NAME, CONF_ID, CONF_SENSOR_CLASS) +import homeassistant.helpers.config_validation as cv -DEPENDENCIES = ["enocean"] +_LOGGER = logging.getLogger(__name__) -CONF_ID = "id" +DEPENDENCIES = ['enocean'] +DEFAULT_NAME = 'EnOcean binary sensor' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ID): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA, +}) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Binary Sensor platform fo EnOcean.""" - dev_id = config.get(CONF_ID, None) - devname = config.get(CONF_NAME, "EnOcean binary sensor") - add_devices([EnOceanBinarySensor(dev_id, devname)]) + dev_id = config.get(CONF_ID) + devname = config.get(CONF_NAME) + sensor_class = config.get(CONF_SENSOR_CLASS) + + add_devices([EnOceanBinarySensor(dev_id, devname, sensor_class)]) class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice): """Representation of EnOcean binary sensors such as wall switches.""" - def __init__(self, dev_id, devname): + def __init__(self, dev_id, devname, sensor_class): """Initialize the EnOcean binary sensor.""" enocean.EnOceanDevice.__init__(self) self.stype = "listener" @@ -32,12 +46,18 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice): self.which = -1 self.onoff = -1 self.devname = devname + self._sensor_class = sensor_class @property def name(self): """The default name for the binary sensor.""" return self.devname + @property + def sensor_class(self): + """Return the class of this sensor.""" + return self._sensor_class + def value_changed(self, value, value2): """Fire an event with the data that have changed. diff --git a/homeassistant/components/enocean.py b/homeassistant/components/enocean.py index 1e70e537c59..7c36e173510 100644 --- a/homeassistant/components/enocean.py +++ b/homeassistant/components/enocean.py @@ -4,23 +4,36 @@ EnOcean Component. For more details about this component, please refer to the documentation at https://home-assistant.io/components/EnOcean/ """ +import logging -DOMAIN = "enocean" +import voluptuous as vol + +from homeassistant.const import CONF_DEVICE +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['enocean==0.31'] -CONF_DEVICE = "device" +_LOGGER = logging.getLogger(__name__) + +DOMAIN = 'enocean' ENOCEAN_DONGLE = None +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_DEVICE): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + def setup(hass, config): """Setup the EnOcean component.""" global ENOCEAN_DONGLE - serial_dev = config[DOMAIN].get(CONF_DEVICE, "/dev/ttyUSB0") + serial_dev = config[DOMAIN].get(CONF_DEVICE) ENOCEAN_DONGLE = EnOceanDongle(hass, serial_dev) + return True diff --git a/homeassistant/components/light/enocean.py b/homeassistant/components/light/enocean.py index 6bd132202fc..772cb55c4e4 100644 --- a/homeassistant/components/light/enocean.py +++ b/homeassistant/components/light/enocean.py @@ -7,27 +7,34 @@ https://home-assistant.io/components/light.enocean/ import logging import math -from homeassistant.components.light import (Light, ATTR_BRIGHTNESS, - SUPPORT_BRIGHTNESS) -from homeassistant.const import CONF_NAME -from homeassistant.components import enocean +import voluptuous as vol +from homeassistant.components.light import ( + Light, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_NAME, CONF_ID) +from homeassistant.components import enocean +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -DEPENDENCIES = ["enocean"] - -CONF_ID = "id" -CONF_SENDER_ID = "sender_id" +DEPENDENCIES = ['enocean'] +DEFAULT_NAME = 'EnOcean Light' +CONF_SENDER_ID = 'sender_id' SUPPORT_ENOCEAN = SUPPORT_BRIGHTNESS +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ID): cv.string, + vol.Required(CONF_SENDER_ID): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the EnOcean light platform.""" - sender_id = config.get(CONF_SENDER_ID, None) - devname = config.get(CONF_NAME, "Enocean actuator") - dev_id = config.get(CONF_ID, [0x00, 0x00, 0x00, 0x00]) + sender_id = config.get(CONF_SENDER_ID) + devname = config.get(CONF_NAME) + dev_id = config.get(CONF_ID) add_devices([EnOceanLight(sender_id, devname, dev_id)]) diff --git a/homeassistant/components/sensor/enocean.py b/homeassistant/components/sensor/enocean.py index 23a59fb5ece..e998b5c9c46 100644 --- a/homeassistant/components/sensor/enocean.py +++ b/homeassistant/components/sensor/enocean.py @@ -4,20 +4,32 @@ Support for EnOcean sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.enocean/ """ +import logging -from homeassistant.const import CONF_NAME +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_NAME, CONF_ID) from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv from homeassistant.components import enocean -DEPENDENCIES = ["enocean"] +_LOGGER = logging.getLogger(__name__) -CONF_ID = "id" +DEFAULT_NAME = 'EnOcean sensor' +DEPENDENCIES = ['enocean'] + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ID): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup an EnOcean sensor device.""" - dev_id = config.get(CONF_ID, None) - devname = config.get(CONF_NAME, None) + dev_id = config.get(CONF_ID) + devname = config.get(CONF_NAME) + add_devices([EnOceanSensor(dev_id, devname)]) diff --git a/homeassistant/components/switch/enocean.py b/homeassistant/components/switch/enocean.py index f0ae26100c3..87a89d148ab 100644 --- a/homeassistant/components/switch/enocean.py +++ b/homeassistant/components/switch/enocean.py @@ -4,25 +4,31 @@ Support for EnOcean switches. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.enocean/ """ - import logging -from homeassistant.const import CONF_NAME +import voluptuous as vol + +from homeassistant.components.switch import PLATFORM_SCHEMA +from homeassistant.const import (CONF_NAME, CONF_ID) from homeassistant.components import enocean from homeassistant.helpers.entity import ToggleEntity - +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -DEPENDENCIES = ["enocean"] +DEFAULT_NAME = 'EnOcean Switch' +DEPENDENCIES = ['enocean'] -CONF_ID = "id" +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ID): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the EnOcean switch platform.""" - dev_id = config.get(CONF_ID, None) - devname = config.get(CONF_NAME, "Enocean actuator") + dev_id = config.get(CONF_ID) + devname = config.get(CONF_NAME) add_devices([EnOceanSwitch(dev_id, devname)]) diff --git a/homeassistant/const.py b/homeassistant/const.py index 77c682868d1..b296a4959b1 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -29,6 +29,7 @@ CONF_BLACKLIST = 'blacklist' CONF_CODE = 'code' CONF_CONDITION = 'condition' CONF_CUSTOMIZE = 'customize' +CONF_DEVICE = 'device' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_DISPLAY_OPTIONS = 'display_options' CONF_ELEVATION = 'elevation' @@ -39,6 +40,7 @@ CONF_FILENAME = 'filename' CONF_HOST = 'host' CONF_HOSTS = 'hosts' CONF_ICON = 'icon' +CONF_ID = 'id' CONF_LATITUDE = 'latitude' CONF_LONGITUDE = 'longitude' CONF_METHOD = 'method' From b199c61c8876e3c99153e0988d03ca6a3e5ff622 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 25 Aug 2016 06:36:41 +0200 Subject: [PATCH 166/193] Migrate to voluptuous (#2955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- .../components/switch/wake_on_lan.py | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/switch/wake_on_lan.py b/homeassistant/components/switch/wake_on_lan.py index 779f4759442..0ecbd51a11b 100644 --- a/homeassistant/components/switch/wake_on_lan.py +++ b/homeassistant/components/switch/wake_on_lan.py @@ -8,27 +8,35 @@ import logging import platform import subprocess as sp -from homeassistant.components.switch import SwitchDevice +import voluptuous as vol + +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +import homeassistant.helpers.config_validation as cv +from homeassistant.const import (CONF_HOST, CONF_NAME) -_LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['wakeonlan==0.2.2'] -DEFAULT_NAME = "Wake on LAN" +_LOGGER = logging.getLogger(__name__) + +CONF_MAC_ADDRESS = 'mac_address' + +DEFAULT_NAME = 'Wake on LAN' DEFAULT_PING_TIMEOUT = 1 +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_MAC_ADDRESS): cv.string, + vol.Optional(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Add wake on lan switch.""" - if config.get('mac_address') is None: - _LOGGER.error("Missing required variable: mac_address") - return False + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + mac_address = config.get(CONF_MAC_ADDRESS) - add_devices_callback([WOLSwitch( - hass, - config.get('name', DEFAULT_NAME), - config.get('host'), - config.get('mac_address'), - )]) + add_devices_callback([WOLSwitch(hass, name, host, mac_address)]) class WOLSwitch(SwitchDevice): From 17631cd728527ac82338b77df13377316333138c Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Thu, 25 Aug 2016 07:18:32 +0200 Subject: [PATCH 167/193] Check config script: various fixes (#2967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- homeassistant/scripts/check_config.py | 9 +++-- homeassistant/util/yaml.py | 17 ++++++---- tests/scripts/test_check_config.py | 48 +++++++++++++++++++++------ 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index 47c1e3b3f64..23e9766928e 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -21,13 +21,14 @@ _LOGGER = logging.getLogger(__name__) # pylint: disable=protected-access MOCKS = { 'load': ("homeassistant.util.yaml.load_yaml", yaml.load_yaml), + 'load*': ("homeassistant.config.load_yaml", yaml.load_yaml), 'get': ("homeassistant.loader.get_component", loader.get_component), 'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml), 'except': ("homeassistant.bootstrap.log_exception", bootstrap.log_exception) } SILENCE = ( - 'homeassistant.util.yaml.clear_secret_cache', + 'homeassistant.bootstrap.clear_secret_cache', 'homeassistant.core._LOGGER.info', 'homeassistant.loader._LOGGER.info', 'homeassistant.bootstrap._LOGGER.info', @@ -114,7 +115,7 @@ def run(script_args: List) -> int: if domain_info: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) - for domain, config in res['components']: + for domain, config in res['components'].items(): print(color(C_HEAD, domain + ':')) dump_dict(config, indent_count=3) else: @@ -207,7 +208,9 @@ def check(config_path): # Patches with local mock functions for key, val in MOCKS.items(): - mock_function = locals()['mock_'+key] + # The * in the key is removed to find the mock_function (side_effect) + # This allows us to use one side_effect to patch multiple locations + mock_function = locals()['mock_' + key.replace('*', '')] PATCHES[key] = patch(val[0], side_effect=mock_function) # Start all patches diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 6696b5434f2..b834ac8048c 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -149,9 +149,13 @@ def _env_var_yaml(loader: SafeLineLoader, def _load_secret_yaml(secret_path: str) -> Dict: """Load the secrets yaml from path.""" - _LOGGER.debug('Loading %s', os.path.join(secret_path, _SECRET_YAML)) + secret_path = os.path.join(secret_path, _SECRET_YAML) + if secret_path in __SECRET_CACHE: + return __SECRET_CACHE[secret_path] + + _LOGGER.debug('Loading %s', secret_path) try: - secrets = load_yaml(os.path.join(secret_path, _SECRET_YAML)) + secrets = load_yaml(secret_path) if 'logger' in secrets: logger = str(secrets['logger']).lower() if logger == 'debug': @@ -160,9 +164,10 @@ def _load_secret_yaml(secret_path: str) -> Dict: _LOGGER.error("secrets.yaml: 'logger: debug' expected," " but 'logger: %s' found", logger) del secrets['logger'] - return secrets except FileNotFoundError: - return {} + secrets = {} + __SECRET_CACHE[secret_path] = secrets + return secrets # pylint: disable=protected-access @@ -171,8 +176,8 @@ def _secret_yaml(loader: SafeLineLoader, """Load secrets and embed it into the configuration YAML.""" secret_path = os.path.dirname(loader.name) while True: - secrets = __SECRET_CACHE.get(secret_path, - _load_secret_yaml(secret_path)) + secrets = _load_secret_yaml(secret_path) + if node.value in secrets: _LOGGER.debug('Secret %s retrieved from secrets.yaml in ' 'folder %s', node.value, secret_path) diff --git a/tests/scripts/test_check_config.py b/tests/scripts/test_check_config.py index 4cad9504f0c..fbd80760c12 100644 --- a/tests/scripts/test_check_config.py +++ b/tests/scripts/test_check_config.py @@ -20,6 +20,21 @@ BASE_CONFIG = ( ) +def change_yaml_files(check_dict): + """Change the ['yaml_files'] property and remove the config path. + + Also removes other files like service.yaml that gets loaded + """ + root = get_test_config_dir() + keys = check_dict['yaml_files'].keys() + check_dict['yaml_files'] = [] + for key in sorted(keys): + if not key.startswith('/'): + check_dict['yaml_files'].append(key) + if key.startswith(root): + check_dict['yaml_files'].append('...' + key[len(root):]) + + def tearDownModule(self): # pylint: disable=invalid-name """Clean files.""" # .HA_VERSION created during bootstrap's config update @@ -39,12 +54,13 @@ class TestCheckConfig(unittest.TestCase): } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('light.yaml')) + change_yaml_files(res) self.assertDictEqual({ 'components': {'light': [{'platform': 'hue'}]}, 'except': {}, 'secret_cache': {}, 'secrets': {}, - 'yaml_files': {} + 'yaml_files': ['.../light.yaml'] }, res) def test_config_component_platform_fail_validation(self): @@ -54,12 +70,13 @@ class TestCheckConfig(unittest.TestCase): } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('component.yaml')) + change_yaml_files(res) self.assertDictEqual({ 'components': {}, 'except': {'http': {'password': 'err123'}}, 'secret_cache': {}, 'secrets': {}, - 'yaml_files': {} + 'yaml_files': ['.../component.yaml'] }, res) files = { @@ -68,13 +85,14 @@ class TestCheckConfig(unittest.TestCase): } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('platform.yaml')) + change_yaml_files(res) self.assertDictEqual({ 'components': {'mqtt': {'keepalive': 60, 'port': 1883, 'protocol': '3.1.1'}}, 'except': {'light.mqtt_json': {'platform': 'mqtt_json'}}, 'secret_cache': {}, 'secrets': {}, - 'yaml_files': {} + 'yaml_files': ['.../platform.yaml'] }, res) def test_component_platform_not_found(self): @@ -85,42 +103,52 @@ class TestCheckConfig(unittest.TestCase): } with patch_yaml_files(files): res = check_config.check(get_test_config_dir('badcomponent.yaml')) + change_yaml_files(res) self.assertDictEqual({ 'components': {}, 'except': {check_config.ERROR_STR: ['Component not found: beer']}, 'secret_cache': {}, 'secrets': {}, - 'yaml_files': {} + 'yaml_files': ['.../badcomponent.yaml'] }, res) res = check_config.check(get_test_config_dir('badplatform.yaml')) + change_yaml_files(res) self.assertDictEqual({ 'components': {}, 'except': {check_config.ERROR_STR: ['Platform not found: light.beer']}, 'secret_cache': {}, 'secrets': {}, - 'yaml_files': {} + 'yaml_files': ['.../badplatform.yaml'] }, res) def test_secrets(self): """Test secrets config checking method.""" files = { - 'secret.yaml': (BASE_CONFIG + - 'http:\n' - ' api_password: !secret http_pw'), + get_test_config_dir('secret.yaml'): ( + BASE_CONFIG + + 'http:\n' + ' api_password: !secret http_pw'), 'secrets.yaml': ('logger: debug\n' 'http_pw: abc123'), } + self.maxDiff = None with patch_yaml_files(files): res = check_config.check(get_test_config_dir('secret.yaml')) + change_yaml_files(res) + + # convert secrets OrderedDict to dict for assertequal + for key, val in res['secret_cache'].items(): + res['secret_cache'][key] = dict(val) + self.assertDictEqual({ 'components': {'http': {'api_password': 'abc123', 'server_port': 8123}}, 'except': {}, - 'secret_cache': {}, + 'secret_cache': {'secrets.yaml': {'http_pw': 'abc123'}}, 'secrets': {'http_pw': 'abc123'}, - 'yaml_files': {'secrets.yaml': True} + 'yaml_files': ['.../secret.yaml', 'secrets.yaml'] }, res) From be1981ca5d42a6a64a71b123653b0beb8674e908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Sandstr=C3=83om?= Date: Thu, 25 Aug 2016 08:20:08 +0000 Subject: [PATCH 168/193] modbus write register service --- homeassistant/components/modbus.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/homeassistant/components/modbus.py b/homeassistant/components/modbus.py index 01f4e72ca0d..1d6ad0e3abc 100644 --- a/homeassistant/components/modbus.py +++ b/homeassistant/components/modbus.py @@ -31,6 +31,12 @@ IP_PORT = "port" _LOGGER = logging.getLogger(__name__) +SERVICE_WRITE_REGISTER = "write_register" + +ATTR_ADDRESS = "address" +ATTR_UNIT = "unit" +ATTR_VALUE = "value" + NETWORK = None TYPE = None @@ -74,6 +80,16 @@ def setup(hass, config): NETWORK.connect() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_modbus) + # Register services for modbus + hass.services.register(DOMAIN, SERVICE_WRITE_REGISTER, write_register) + + def write_register(service): + """Write modbus register.""" + unit = int(float(service.data.get(ATTR_UNIT))) + address = int(float(service.data.get(ATTR_ADDRESS))) + value = int(float(service.data.get(ATTR_VALUE))) + NETWORK.write_register(address, value, unit=unit) + hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_modbus) return True From 826ec9b9d7140451c030d978e09f31517b5b938a Mon Sep 17 00:00:00 2001 From: Teagan Glenn Date: Thu, 25 Aug 2016 06:47:07 -0600 Subject: [PATCH 169/193] Add a Fan component and support for an Insteon Hub Fan (#2964) * Fan component and service definitions * Insteon Hub fan support --- homeassistant/components/fan/__init__.py | 224 ++++++++++++++++++ homeassistant/components/fan/insteon_hub.py | 71 ++++++ homeassistant/components/fan/services.yaml | 45 ++++ homeassistant/components/insteon_hub.py | 80 ++++++- homeassistant/components/light/insteon_hub.py | 74 +++--- requirements_all.txt | 2 +- tests/components/fan/__init__.py | 1 + tests/components/fan/test_insteon_hub.py | 76 ++++++ 8 files changed, 524 insertions(+), 49 deletions(-) create mode 100644 homeassistant/components/fan/__init__.py create mode 100644 homeassistant/components/fan/insteon_hub.py create mode 100644 homeassistant/components/fan/services.yaml create mode 100644 tests/components/fan/__init__.py create mode 100644 tests/components/fan/test_insteon_hub.py diff --git a/homeassistant/components/fan/__init__.py b/homeassistant/components/fan/__init__.py new file mode 100644 index 00000000000..d4af7562920 --- /dev/null +++ b/homeassistant/components/fan/__init__.py @@ -0,0 +1,224 @@ +""" +Provides functionality to interact with fans. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/fan/ +""" +import logging +import os + +import voluptuous as vol + +from homeassistant.components import group +from homeassistant.config import load_yaml_config_file +from homeassistant.const import ( + STATE_OFF, SERVICE_TURN_ON, + SERVICE_TURN_OFF, ATTR_ENTITY_ID) +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity_component import EntityComponent +from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa +import homeassistant.helpers.config_validation as cv + + +DOMAIN = 'fan' +SCAN_INTERVAL = 30 + +GROUP_NAME_ALL_FANS = 'all fans' +ENTITY_ID_ALL_FANS = group.ENTITY_ID_FORMAT.format(GROUP_NAME_ALL_FANS) + +ENTITY_ID_FORMAT = DOMAIN + '.{}' + +# Bitfield of features supported by the fan entity +ATTR_SUPPORTED_FEATURES = 'supported_features' +SUPPORT_SET_SPEED = 1 +SUPPORT_OSCILLATE = 2 + +SERVICE_SET_SPEED = 'set_speed' +SERVICE_OSCILLATE = 'oscillate' + +SPEED_OFF = 'off' +SPEED_LOW = 'low' +SPEED_MED = 'med' +SPEED_HIGH = 'high' + +ATTR_SPEED = 'speed' +ATTR_SPEED_LIST = 'speed_list' +ATTR_OSCILLATE = 'oscillate' + +PROP_TO_ATTR = { + 'speed': ATTR_SPEED, + 'speed_list': ATTR_SPEED_LIST, + 'oscillate': ATTR_OSCILLATE, + 'supported_features': ATTR_SUPPORTED_FEATURES, +} # type: dict + +FAN_SET_SPEED_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_SPEED): cv.string +}) # type: dict + +FAN_TURN_ON_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Optional(ATTR_SPEED): cv.string +}) # type: dict + +FAN_TURN_OFF_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids +}) # type: dict + +FAN_OSCILLATE_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_OSCILLATE): cv.boolean +}) # type: dict + +_LOGGER = logging.getLogger(__name__) + + +def is_on(hass, entity_id: str=None) -> bool: + """Return if the fans are on based on the statemachine.""" + entity_id = entity_id or ENTITY_ID_ALL_FANS + return not hass.states.is_state(entity_id, STATE_OFF) + + +# pylint: disable=too-many-arguments +def turn_on(hass, entity_id: str=None, speed: str=None) -> None: + """Turn all or specified fan on.""" + data = { + key: value for key, value in [ + (ATTR_ENTITY_ID, entity_id), + (ATTR_SPEED, speed), + ] if value is not None + } + + hass.services.call(DOMAIN, SERVICE_TURN_ON, data) + + +def turn_off(hass, entity_id: str=None) -> None: + """Turn all or specified fan off.""" + data = { + ATTR_ENTITY_ID: entity_id, + } + + hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) + + +def oscillate(hass, entity_id: str=None, should_oscillate: bool=True) -> None: + """Set oscillation on all or specified fan.""" + data = { + key: value for key, value in [ + (ATTR_ENTITY_ID, entity_id), + (ATTR_OSCILLATE, should_oscillate), + ] if value is not None + } + + hass.services.call(DOMAIN, SERVICE_OSCILLATE, data) + + +def set_speed(hass, entity_id: str=None, speed: str=None) -> None: + """Set speed for all or specified fan.""" + data = { + key: value for key, value in [ + (ATTR_ENTITY_ID, entity_id), + (ATTR_SPEED, speed), + ] if value is not None + } + + hass.services.call(DOMAIN, SERVICE_SET_SPEED, data) + + +# pylint: disable=too-many-branches, too-many-locals, too-many-statements +def setup(hass, config: dict) -> None: + """Expose fan control via statemachine and services.""" + component = EntityComponent( + _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_FANS) + component.setup(config) + + def handle_fan_service(service: str) -> None: + """Hande service call for fans.""" + # Get the validated data + params = service.data.copy() + + # Convert the entity ids to valid fan ids + target_fans = component.extract_from_service(service) + params.pop(ATTR_ENTITY_ID, None) + + service_fun = None + for service_def in [SERVICE_TURN_ON, SERVICE_TURN_OFF, + SERVICE_SET_SPEED, SERVICE_OSCILLATE]: + if service_def == service.service: + service_fun = service_def + break + + if service_fun: + for fan in target_fans: + getattr(fan, service_fun)(**params) + + for fan in target_fans: + if fan.should_poll: + fan.update_ha_state(True) + return + + # Listen for fan service calls. + descriptions = load_yaml_config_file( + os.path.join(os.path.dirname(__file__), 'services.yaml')) + hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_fan_service, + descriptions.get(SERVICE_TURN_ON), + schema=FAN_TURN_ON_SCHEMA) + + hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_fan_service, + descriptions.get(SERVICE_TURN_OFF), + schema=FAN_TURN_OFF_SCHEMA) + + hass.services.register(DOMAIN, SERVICE_SET_SPEED, handle_fan_service, + descriptions.get(SERVICE_SET_SPEED), + schema=FAN_SET_SPEED_SCHEMA) + + hass.services.register(DOMAIN, SERVICE_OSCILLATE, handle_fan_service, + descriptions.get(SERVICE_OSCILLATE), + schema=FAN_OSCILLATE_SCHEMA) + + return True + + +class FanEntity(Entity): + """Representation of a fan.""" + + # pylint: disable=no-self-use, abstract-method + + def set_speed(self: Entity, speed: str) -> None: + """Set the speed of the fan.""" + pass + + def turn_on(self: Entity, speed: str=None) -> None: + """Turn on the fan.""" + pass + + def turn_off(self: Entity) -> None: + """Turn off the fan.""" + pass + + def oscillate(self: Entity) -> None: + """Oscillate the fan.""" + pass + + @property + def speed_list(self: Entity) -> list: + """Get the list of available speeds.""" + return [] + + @property + def state_attributes(self: Entity) -> dict: + """Return optional state attributes.""" + data = {} # type: dict + + for prop, attr in PROP_TO_ATTR.items(): + value = getattr(self, prop) + if value is not None: + data[attr] = value + + return data + + @property + def supported_features(self: Entity) -> int: + """Flag supported features.""" + return 0 diff --git a/homeassistant/components/fan/insteon_hub.py b/homeassistant/components/fan/insteon_hub.py new file mode 100644 index 00000000000..2f24bb0bc9b --- /dev/null +++ b/homeassistant/components/fan/insteon_hub.py @@ -0,0 +1,71 @@ +""" +Support for Insteon FanLinc. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/fan.insteon/ +""" + +import logging + +from homeassistant.components.fan import (FanEntity, SUPPORT_SET_SPEED, + SPEED_OFF, SPEED_LOW, SPEED_MED, + SPEED_HIGH) +from homeassistant.components.insteon_hub import (InsteonDevice, INSTEON, + filter_devices) +from homeassistant.const import STATE_UNKNOWN + +_LOGGER = logging.getLogger(__name__) + +DEVICE_CATEGORIES = [ + { + 'DevCat': 1, + 'SubCat': [46] + } +] + +DEPENDENCIES = ['insteon_hub'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Insteon Hub fan platform.""" + devs = [] + for device in filter_devices(INSTEON.devices, DEVICE_CATEGORIES): + devs.append(InsteonFanDevice(device)) + add_devices(devs) + + +class InsteonFanDevice(InsteonDevice, FanEntity): + """Represet an insteon fan device.""" + + def __init__(self, node: object) -> None: + """Initialize the device.""" + super(InsteonFanDevice, self).__init__(node) + self.speed = STATE_UNKNOWN # Insteon hub can't get state via REST + + def turn_on(self, speed: str=None): + """Turn the fan on.""" + self.set_speed(speed if speed else SPEED_MED) + + def turn_off(self): + """Turn the fan off.""" + self.set_speed(SPEED_OFF) + + def set_speed(self, speed: str) -> None: + """Set the fan speed.""" + if self._send_command('fan', payload={'speed', speed}): + self.speed = speed + + @property + def supported_features(self) -> int: + """Get the supported features for device.""" + return SUPPORT_SET_SPEED + + @property + def speed_list(self) -> list: + """Get the available speeds for the fan.""" + return [SPEED_OFF, SPEED_LOW, SPEED_MED, SPEED_HIGH] + + @property + def state(self) -> str: + """Get the current device state.""" + return self.speed diff --git a/homeassistant/components/fan/services.yaml b/homeassistant/components/fan/services.yaml new file mode 100644 index 00000000000..4f20e6036ce --- /dev/null +++ b/homeassistant/components/fan/services.yaml @@ -0,0 +1,45 @@ +# Describes the format for available fan services + +set_speed: + description: Sets fan speed + + fields: + entity_id: + description: Name(s) of the entities to set + example: 'fan.living_room' + + speed: + description: Speed setting + example: 'low' + +turn_on: + description: Turns fan on + + fields: + entity_id: + description: Names(s) of the entities to turn on + example: 'fan.living_room' + + speed: + description: Speed setting + example: 'high' + +turn_off: + description: Turns fan off + + fields: + entity_id: + description: Names(s) of the entities to turn off + example: 'fan.living_room' + +oscillate: + description: Oscillates the fan + + fields: + entity_id: + description: Name(s) of the entities to oscillate + example: 'fan.desk_fan' + + oscillate: + description: Flag to turn on/off oscillation + example: True \ No newline at end of file diff --git a/homeassistant/components/insteon_hub.py b/homeassistant/components/insteon_hub.py index 306acab5361..3ad107886b8 100644 --- a/homeassistant/components/insteon_hub.py +++ b/homeassistant/components/insteon_hub.py @@ -8,37 +8,93 @@ import logging from homeassistant.const import CONF_API_KEY, CONF_PASSWORD, CONF_USERNAME from homeassistant.helpers import validate_config, discovery +from homeassistant.helpers.entity import Entity + +DOMAIN = 'insteon_hub' # type: str +REQUIREMENTS = ['insteon_hub==0.5.0'] # type: list +INSTEON = None # type: Insteon +DEVCAT = 'DevCat' # type: str +SUBCAT = 'SubCat' # type: str +DEVICE_CLASSES = ['light', 'fan'] # type: list -DOMAIN = "insteon_hub" -REQUIREMENTS = ['insteon_hub==0.4.5'] -INSTEON = None _LOGGER = logging.getLogger(__name__) -def setup(hass, config): - """Setup Insteon Hub component. +def _is_successful(response: dict) -> bool: + """Check http response for successful status.""" + return 'status' in response and response['status'] == 'succeeded' - This will automatically import associated lights. - """ + +def filter_devices(devices: list, categories: list) -> list: + """Filter insteon device list by category/subcategory.""" + categories = (categories + if isinstance(categories, list) + else [categories]) + matching_devices = [] + for device in devices: + if any( + device.DevCat == c[DEVCAT] and + (SUBCAT not in c or device.SubCat in c[SUBCAT]) + for c in categories): + matching_devices.append(device) + return matching_devices + + +def setup(hass, config: dict) -> bool: + """Setup Insteon Hub component.""" if not validate_config( config, {DOMAIN: [CONF_USERNAME, CONF_PASSWORD, CONF_API_KEY]}, _LOGGER): return False - import insteon + from insteon import Insteon username = config[DOMAIN][CONF_USERNAME] password = config[DOMAIN][CONF_PASSWORD] api_key = config[DOMAIN][CONF_API_KEY] global INSTEON - INSTEON = insteon.Insteon(username, password, api_key) + INSTEON = Insteon(username, password, api_key) if INSTEON is None: - _LOGGER.error("Could not connect to Insteon service.") + _LOGGER.error('Could not connect to Insteon service.') return - discovery.load_platform(hass, 'light', DOMAIN, {}, config) - + for device_class in DEVICE_CLASSES: + discovery.load_platform(hass, device_class, DOMAIN, {}, config) return True + + +class InsteonDevice(Entity): + """Represents an insteon device.""" + + def __init__(self: Entity, node: object) -> None: + """Initialize the insteon device.""" + self._node = node + + def update(self: Entity) -> None: + """Update state of the device.""" + pass + + @property + def name(self: Entity) -> str: + """Name of the insteon device.""" + return self._node.DeviceName + + @property + def unique_id(self: Entity) -> str: + """Unique identifier for the device.""" + return self._node.DeviceID + + @property + def supported_features(self: Entity) -> int: + """Supported feature flags.""" + return 0 + + def _send_command(self: Entity, command: str, level: int=None, + payload: dict=None) -> bool: + """Send command to insteon device.""" + resp = self._node.send_command(command, payload=payload, level=level, + wait=True) + return _is_successful(resp) diff --git a/homeassistant/components/light/insteon_hub.py b/homeassistant/components/light/insteon_hub.py index 70beadb6c1d..29254735ced 100644 --- a/homeassistant/components/light/insteon_hub.py +++ b/homeassistant/components/light/insteon_hub.py @@ -4,74 +4,76 @@ Support for Insteon Hub lights. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/insteon_hub/ """ -from homeassistant.components.insteon_hub import INSTEON +from homeassistant.components.insteon_hub import (INSTEON, InsteonDevice) from homeassistant.components.light import (ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light) SUPPORT_INSTEON_HUB = SUPPORT_BRIGHTNESS +DEPENDENCIES = ['insteon_hub'] + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Insteon Hub light platform.""" devs = [] for device in INSTEON.devices: if device.DeviceCategory == "Switched Lighting Control": - devs.append(InsteonToggleDevice(device)) + devs.append(InsteonLightDevice(device)) if device.DeviceCategory == "Dimmable Lighting Control": - devs.append(InsteonToggleDevice(device)) + devs.append(InsteonDimmableDevice(device)) add_devices(devs) -class InsteonToggleDevice(Light): - """An abstract Class for an Insteon node.""" +class InsteonLightDevice(InsteonDevice, Light): + """A representation of a light device.""" - def __init__(self, node): + def __init__(self, node: object) -> None: """Initialize the device.""" - self.node = node + super(InsteonLightDevice, self).__init__(node) self._value = 0 - @property - def name(self): - """Return the the name of the node.""" - return self.node.DeviceName - - @property - def unique_id(self): - """Return the ID of this insteon node.""" - return self.node.DeviceID - - @property - def brightness(self): - """Return the brightness of this light between 0..255.""" - return self._value / 100 * 255 - - def update(self): - """Update state of the sensor.""" - resp = self.node.send_command('get_status', wait=True) + def update(self) -> None: + """Update state of the device.""" + resp = self._node.send_command('get_status', wait=True) try: self._value = resp['response']['level'] except KeyError: pass @property - def is_on(self): + def is_on(self) -> None: """Return the boolean response if the node is on.""" return self._value != 0 + def turn_on(self, **kwargs) -> None: + """Turn device on.""" + if self._send_command('on'): + self._value = 100 + + def turn_off(self, **kwargs) -> None: + """Turn device off.""" + if self._send_command('off'): + self._value = 0 + + +class InsteonDimmableDevice(InsteonLightDevice): + """A representation for a dimmable device.""" + @property - def supported_features(self): + def brightness(self) -> int: + """Return the brightness of this light between 0..255.""" + return round(self._value / 100 * 255, 0) # type: int + + @property + def supported_features(self) -> int: """Flag supported features.""" return SUPPORT_INSTEON_HUB - def turn_on(self, **kwargs): + def turn_on(self, **kwargs) -> None: """Turn device on.""" + level = 100 # type: int if ATTR_BRIGHTNESS in kwargs: - self._value = kwargs[ATTR_BRIGHTNESS] / 255 * 100 - self.node.send_command('on', self._value) - else: - self._value = 100 - self.node.send_command('on') + level = round(kwargs[ATTR_BRIGHTNESS] / 255 * 100, 0) # type: int - def turn_off(self, **kwargs): - """Turn device off.""" - self.node.send_command('off') + if self._send_command('on', level=level): + self._value = level diff --git a/requirements_all.txt b/requirements_all.txt index e9d125d764a..2bb39e5e69a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -204,7 +204,7 @@ https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0 influxdb==3.0.0 # homeassistant.components.insteon_hub -insteon_hub==0.4.5 +insteon_hub==0.5.0 # homeassistant.components.media_player.kodi jsonrpc-requests==0.3 diff --git a/tests/components/fan/__init__.py b/tests/components/fan/__init__.py new file mode 100644 index 00000000000..251a118e32e --- /dev/null +++ b/tests/components/fan/__init__.py @@ -0,0 +1 @@ +"""Test fan component plaforms.""" diff --git a/tests/components/fan/test_insteon_hub.py b/tests/components/fan/test_insteon_hub.py new file mode 100644 index 00000000000..270687c9fd3 --- /dev/null +++ b/tests/components/fan/test_insteon_hub.py @@ -0,0 +1,76 @@ +"""Tests for the insteon hub fan platform.""" +import unittest + +from homeassistant.const import STATE_OFF, STATE_UNKNOWN +from homeassistant.components.fan import (SPEED_LOW, SPEED_MED, SPEED_HIGH) +from homeassistant.components.fan.insteon_hub import (InsteonFanDevice, + SUPPORT_SET_SPEED) + + +class Node(object): + """Fake insteon node.""" + + def __init__(self, name, id, dev_cat, sub_cat): + """Initialize fake insteon node.""" + self.DeviceName = name + self.DeviceID = id + self.DevCat = dev_cat + self.SubCat = sub_cat + self.response = None + + def send_command(self, command, payload, level, wait): + """Send fake command.""" + return self.response + + +class TestInsteonHubFanDevice(unittest.TestCase): + """Test around insteon hub fan device methods.""" + + _NODE = Node('device', '12345', '1', '46') + + def setUp(self): + """Initialize test data.""" + self._DEVICE = InsteonFanDevice(self._NODE) + + def tearDown(self): + """Tear down test data.""" + self._DEVICE = None + + def test_properties(self): + """Test basic properties.""" + self.assertEqual(self._NODE.DeviceName, self._DEVICE.name) + self.assertEqual(self._NODE.DeviceID, self._DEVICE.unique_id) + self.assertEqual(SUPPORT_SET_SPEED, self._DEVICE.supported_features) + + for speed in [STATE_OFF, SPEED_LOW, SPEED_MED, SPEED_HIGH]: + self.assertIn(speed, self._DEVICE.speed_list) + + def test_turn_on(self): + """Test the turning on device.""" + self._NODE.response = { + 'status': 'succeeded' + } + self.assertEqual(STATE_UNKNOWN, self._DEVICE.state) + self._DEVICE.turn_on() + + self.assertNotEqual(STATE_OFF, self._DEVICE.state) + + self._DEVICE.turn_on(SPEED_MED) + + self.assertEqual(SPEED_MED, self._DEVICE.state) + + self._NODE.response = { + } + self._DEVICE.turn_on(SPEED_HIGH) + + self.assertNotEqual(SPEED_HIGH, self._DEVICE.state) + + def test_turn_off(self): + """Test turning off device.""" + self._NODE.response = { + 'status': 'succeeded' + } + self.assertEqual(STATE_UNKNOWN, self._DEVICE.state) + self._DEVICE.turn_off() + + self.assertEqual(STATE_OFF, self._DEVICE.state) From 34f57ebdc96e6e750d2b327e706d1ea67db863b7 Mon Sep 17 00:00:00 2001 From: Landrash Date: Thu, 25 Aug 2016 18:55:37 +0200 Subject: [PATCH 170/193] Fix reference to wrong components in tests for cameras (#1) (#2975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 👍 --- tests/components/camera/test_generic.py | 2 +- tests/components/camera/test_local_file.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/components/camera/test_generic.py b/tests/components/camera/test_generic.py index f57ef62c0d4..df80b48e36b 100644 --- a/tests/components/camera/test_generic.py +++ b/tests/components/camera/test_generic.py @@ -1,4 +1,4 @@ -"""The tests for UVC camera module.""" +"""The tests for generic camera component.""" import unittest from unittest import mock diff --git a/tests/components/camera/test_local_file.py b/tests/components/camera/test_local_file.py index d8ec570a8b0..c30f59968e8 100644 --- a/tests/components/camera/test_local_file.py +++ b/tests/components/camera/test_local_file.py @@ -1,4 +1,4 @@ -"""The tests for UVC camera module.""" +"""The tests for local file camera component.""" from tempfile import NamedTemporaryFile import unittest from unittest import mock @@ -12,7 +12,7 @@ from tests.common import get_test_home_assistant class TestLocalCamera(unittest.TestCase): - """Test the generic camera platform.""" + """Test the local file camera component.""" def setUp(self): """Setup things to be run when tests are started.""" From d1e94b958f6c8ab004c3cf87f165c0881c671810 Mon Sep 17 00:00:00 2001 From: MartinHjelmare Date: Thu, 25 Aug 2016 19:07:22 +0200 Subject: [PATCH 171/193] Extract mqtt string into constant and add log --- homeassistant/components/mysensors.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index 8a53bc011cd..5169e86ff04 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -31,6 +31,7 @@ DEFAULT_TCP_PORT = 5003 DOMAIN = 'mysensors' DEPENDENCIES = [] +MQTT_COMPONENT = 'mqtt' REQUIREMENTS = [ 'https://github.com/theolind/pymysensors/archive/' '8ce98b7fb56f7921a808eb66845ce8b2c455c81e.zip#pymysensors==0.7.1'] @@ -64,10 +65,10 @@ def setup(hass, config): # pylint: disable=too-many-locals out_prefix): """Return gateway after setup of the gateway.""" # pylint: disable=too-many-arguments - if device in 'mqtt': - if not setup_component(hass, 'mqtt', config): + if device == MQTT_COMPONENT: + if not setup_component(hass, MQTT_COMPONENT, config): return - mqtt = get_component('mqtt') + mqtt = get_component(MQTT_COMPONENT) retain = config[DOMAIN].get(CONF_RETAIN, True) def pub_callback(topic, payload, qos, retain): @@ -139,6 +140,11 @@ def setup(hass, config): # pylint: disable=too-many-locals if GATEWAYS[device] is None: GATEWAYS.pop(device) + if not GATEWAYS: + _LOGGER.error( + 'No devices could be setup as gateways, check your configuration') + return False + for component in 'sensor', 'switch', 'light', 'binary_sensor': discovery.load_platform(hass, component, DOMAIN, {}, config) @@ -228,7 +234,7 @@ class GatewayWrapper(object): """Return a new callback function.""" def node_update(update_type, node_id): """Callback for node updates from the MySensors gateway.""" - _LOGGER.debug('update %s: node %s', update_type, node_id) + _LOGGER.debug('Update %s: node %s', update_type, node_id) for callback in self.platform_callbacks: callback(self, node_id) @@ -299,7 +305,7 @@ class MySensorsDeviceEntity(object): try: attr[set_req(value_type).name] = value except ValueError: - _LOGGER.error('value_type %s is not valid for mysensors ' + _LOGGER.error('Value_type %s is not valid for mysensors ' 'version %s', value_type, self.gateway.version) return attr From 354f4b474003ecc297c0ebdba07db43fa7845f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Thu, 25 Aug 2016 19:52:48 +0200 Subject: [PATCH 172/193] Upgrade rfxtrx lib (#2974) --- homeassistant/components/rfxtrx.py | 4 ++-- homeassistant/components/sensor/rfxtrx.py | 6 ++---- requirements_all.txt | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/rfxtrx.py b/homeassistant/components/rfxtrx.py index f15bd703ca1..3871058a27e 100644 --- a/homeassistant/components/rfxtrx.py +++ b/homeassistant/components/rfxtrx.py @@ -14,7 +14,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.helpers.entity import Entity from homeassistant.const import (ATTR_ENTITY_ID, TEMP_CELSIUS) -REQUIREMENTS = ['pyRFXtrx==0.10.1'] +REQUIREMENTS = ['pyRFXtrx==0.11.0'] DOMAIN = "rfxtrx" @@ -42,7 +42,7 @@ DATA_TYPES = OrderedDict([ ('Total usage', 'W'), ('Sound', ''), ('Sensor Status', ''), - ('Unknown', '')]) + ('Counter value', '')]) RECEIVED_EVT_SUBSCRIBERS = [] RFX_DEVICES = {} diff --git a/homeassistant/components/sensor/rfxtrx.py b/homeassistant/components/sensor/rfxtrx.py index 67aff8956d3..f9f7270c8e3 100644 --- a/homeassistant/components/sensor/rfxtrx.py +++ b/homeassistant/components/sensor/rfxtrx.py @@ -84,7 +84,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): pkt_id = "".join("{0:02x}".format(x) for x in event.data) _LOGGER.info("Automatic add rfxtrx.sensor: %s", - device_id) + pkt_id) data_type = "Unknown" for _data_type in DATA_TYPES: @@ -109,10 +109,8 @@ class RfxtrxSensor(Entity): self.event = event self._name = name self.should_fire_event = should_fire_event - if data_type not in DATA_TYPES: - data_type = "Unknown" self.data_type = data_type - self._unit_of_measurement = DATA_TYPES[data_type] + self._unit_of_measurement = DATA_TYPES.get(data_type, '') def __str__(self): """Return the name of the sensor.""" diff --git a/requirements_all.txt b/requirements_all.txt index 2bb39e5e69a..38466718e8d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -293,7 +293,7 @@ pushetta==1.0.15 py-cpuinfo==0.2.3 # homeassistant.components.rfxtrx -pyRFXtrx==0.10.1 +pyRFXtrx==0.11.0 # homeassistant.components.notify.xmpp pyasn1-modules==0.0.8 From 2eadae2039767e540c7b0b760fa0808181415e66 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 25 Aug 2016 21:55:03 +0200 Subject: [PATCH 173/193] add homematic hub device with variable support / update pyhomematic with new device / add cover support (#2981) --- .../components/binary_sensor/homematic.py | 4 +- homeassistant/components/homematic.py | 106 +++++++++++++++--- homeassistant/components/sensor/homematic.py | 8 +- requirements_all.txt | 2 +- 4 files changed, 101 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/binary_sensor/homematic.py b/homeassistant/components/binary_sensor/homematic.py index 8e874079ee6..117642c65f1 100644 --- a/homeassistant/components/binary_sensor/homematic.py +++ b/homeassistant/components/binary_sensor/homematic.py @@ -20,7 +20,9 @@ SENSOR_TYPES_CLASS = { "SmokeV2": "smoke", "Motion": "motion", "MotionV2": "motion", - "RemoteMotion": None + "RemoteMotion": None, + "WeatherSensor": None, + "TiltSensor": None, } diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index 942e4b1c741..0a0424188c4 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -14,11 +14,14 @@ import homeassistant.helpers.config_validation as cv from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN, CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM) from homeassistant.helpers.entity import Entity +from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers import discovery from homeassistant.config import load_yaml_config_file DOMAIN = 'homematic' -REQUIREMENTS = ["pyhomematic==0.1.11"] +REQUIREMENTS = ["pyhomematic==0.1.13"] + +ENTITY_ID_FORMAT = DOMAIN + '.{}' HOMEMATIC = None HOMEMATIC_LINK_DELAY = 0.5 @@ -27,8 +30,8 @@ DISCOVER_SWITCHES = 'homematic.switch' DISCOVER_LIGHTS = 'homematic.light' DISCOVER_SENSORS = 'homematic.sensor' DISCOVER_BINARY_SENSORS = 'homematic.binary_sensor' -DISCOVER_ROLLERSHUTTER = 'homematic.rollershutter' -DISCOVER_THERMOSTATS = 'homematic.climate' +DISCOVER_COVER = 'homematic.cover' +DISCOVER_CLIMATE = 'homematic.climate' ATTR_DISCOVER_DEVICES = 'devices' ATTR_PARAM = 'param' @@ -47,11 +50,12 @@ HM_DEVICE_TYPES = { DISCOVER_SENSORS: ['SwitchPowermeter', 'Motion', 'MotionV2', 'RemoteMotion', 'ThermostatWall', 'AreaThermostat', 'RotaryHandleSensor', 'WaterSensor', 'PowermeterGas', - 'LuxSensor'], - DISCOVER_THERMOSTATS: ['Thermostat', 'ThermostatWall', 'MAXThermostat'], + 'LuxSensor', 'WeatherSensor', 'WeatherStation'], + DISCOVER_CLIMATE: ['Thermostat', 'ThermostatWall', 'MAXThermostat'], DISCOVER_BINARY_SENSORS: ['ShutterContact', 'Smoke', 'SmokeV2', 'Motion', - 'MotionV2', 'RemoteMotion'], - DISCOVER_ROLLERSHUTTER: ['Blind'] + 'MotionV2', 'RemoteMotion', 'WeatherSensor', + 'TiltSensor'], + DISCOVER_COVER: ['Blind'] } HM_IGNORE_DISCOVERY_NODE = [ @@ -133,9 +137,11 @@ SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({ def setup(hass, config): """Setup the Homematic component.""" global HOMEMATIC, HOMEMATIC_LINK_DELAY - from pyhomematic import HMConnection + component = EntityComponent(_LOGGER, DOMAIN, hass) + hm_hub = HMHub() + local_ip = config[DOMAIN].get(CONF_LOCAL_IP) local_port = config[DOMAIN].get(CONF_LOCAL_PORT) remote_ip = config[DOMAIN].get(CONF_REMOTE_IP) @@ -150,11 +156,13 @@ def setup(hass, config): return False # Create server thread - bound_system_callback = partial(system_callback_handler, hass, config) + bound_system_callback = partial(_system_callback_handler, hass, config) + bound_event_callback = partial(_event_callback_handler, hm_hub) HOMEMATIC = HMConnection(local=local_ip, localport=local_port, remote=remote_ip, remoteport=remote_port, + eventcallback=bound_event_callback, systemcallback=bound_system_callback, resolvenames=resolvenames, rpcusername=username, @@ -177,11 +185,19 @@ def setup(hass, config): descriptions[DOMAIN][SERVICE_VIRTUALKEY], SCHEMA_SERVICE_VIRTUALKEY) + hm_hub.init_data() + component.add_entities([hm_hub]) return True +def _event_callback_handler(hm_hub, interface_id, address, value_key, value): + """Callback handler for events.""" + if not address: + hm_hub.update_hm_variable(value_key, value) + + # pylint: disable=too-many-branches -def system_callback_handler(hass, config, src, *args): +def _system_callback_handler(hass, config, src, *args): """Callback handler.""" if src == 'newDevices': _LOGGER.debug("newDevices with: %s", str(args)) @@ -212,10 +228,10 @@ def system_callback_handler(hass, config, src, *args): for component_name, discovery_type in ( ('switch', DISCOVER_SWITCHES), ('light', DISCOVER_LIGHTS), - ('rollershutter', DISCOVER_ROLLERSHUTTER), + ('rollershutter', DISCOVER_COVER), ('binary_sensor', DISCOVER_BINARY_SENSORS), ('sensor', DISCOVER_SENSORS), - ('climate', DISCOVER_THERMOSTATS)): + ('climate', DISCOVER_CLIMATE)): # Get all devices of a specific type found_devices = _get_devices(discovery_type, key_dict) @@ -423,16 +439,74 @@ def _hm_service_virtualkey(call): hmdevice.actionNodeData(param, 1, channel) +class HMHub(Entity): + """The Homematic hub. I.e. CCU2/HomeGear.""" + + def __init__(self): + """Initialize Homematic hub.""" + self._data = {} + + @property + def name(self): + """Return the name of the device.""" + return 'Homematic' + + @property + def state(self): + """Return the state of the entity.""" + state = HOMEMATIC.getServiceMessages() + if state is None: + return STATE_UNKNOWN + + return len(state) + + @property + def device_state_attributes(self): + """Return device specific state attributes.""" + return self._data + + def init_data(self): + """Init variable to object.""" + hm_var = HOMEMATIC.getAllSystemVariables() + for var, val in hm_var: + self._data[var] = val + + def update_hm_variable(self, variable, value): + """Update homematic variable from Homematic.""" + if variable not in self._data: + return + + # if value have change, update HASS + if self._data[variable] != value: + self._data[variable] = value + self.update_ha_state() + + @property + def should_poll(self): + """Return false. Homematic states are pushed by the XML RPC Server.""" + return False + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + return '#' + + @property + def icon(self): + """Return the icon to use in the frontend, if any.""" + return "mdi:gradient" + + class HMDevice(Entity): """The Homematic device base object.""" # pylint: disable=too-many-instance-attributes def __init__(self, config): """Initialize a generic Homematic device.""" - self._name = config.get(ATTR_NAME, None) - self._address = config.get(ATTR_ADDRESS, None) - self._channel = config.get(ATTR_CHANNEL, 1) - self._state = config.get(ATTR_PARAM, None) + self._name = config.get(ATTR_NAME) + self._address = config.get(ATTR_ADDRESS) + self._channel = config.get(ATTR_CHANNEL) + self._state = config.get(ATTR_PARAM) self._data = {} self._hmdevice = None self._connected = False diff --git a/homeassistant/components/sensor/homematic.py b/homeassistant/components/sensor/homematic.py index 66526408567..35cc4aea42b 100644 --- a/homeassistant/components/sensor/homematic.py +++ b/homeassistant/components/sensor/homematic.py @@ -31,7 +31,13 @@ HM_UNIT_HA_CAST = { "ENERGY_COUNTER": "Wh", "GAS_POWER": "m3", "GAS_ENERGY_COUNTER": "m3", - "LUX": "lux" + "LUX": "lux", + "RAIN_COUNTER": "mm", + "WIND_SPEED": "km/h", + "WIND_DIRECTION": "°", + "WIND_DIRECTION_RANGE": "°", + "SUNSHINEDURATION": "#", + "AIR_PRESSURE": "hPa", } diff --git a/requirements_all.txt b/requirements_all.txt index 38466718e8d..fd16391f6e6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -321,7 +321,7 @@ pyenvisalink==1.0 pyfttt==0.3 # homeassistant.components.homematic -pyhomematic==0.1.11 +pyhomematic==0.1.13 # homeassistant.components.device_tracker.icloud pyicloud==0.9.1 From d611010a6e8fe9abc94006f2d678ff8276998c70 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Fri, 26 Aug 2016 05:09:48 +0300 Subject: [PATCH 174/193] Fix reading dht config values (#2956) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- homeassistant/components/sensor/dht.py | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/sensor/dht.py b/homeassistant/components/sensor/dht.py index df0cb4d3b69..109e539c599 100644 --- a/homeassistant/components/sensor/dht.py +++ b/homeassistant/components/sensor/dht.py @@ -18,9 +18,13 @@ REQUIREMENTS = ['http://github.com/adafruit/Adafruit_Python_DHT/archive/' '#Adafruit_DHT==1.3.0'] _LOGGER = logging.getLogger(__name__) +CONF_PIN = 'pin' +CONF_SENSOR = 'sensor' +SENSOR_TEMPERATURE = 'temperature' +SENSOR_HUMIDITY = 'humidity' SENSOR_TYPES = { - 'temperature': ['Temperature', None], - 'humidity': ['Humidity', '%'] + SENSOR_TEMPERATURE: ['Temperature', None], + SENSOR_HUMIDITY: ['Humidity', '%'] } DEFAULT_NAME = "DHT Sensor" # Return cached results if last scan was less then this time ago @@ -33,15 +37,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): # pylint: disable=import-error import Adafruit_DHT - SENSOR_TYPES['temperature'][1] = hass.config.units.temperature_unit + SENSOR_TYPES[SENSOR_TEMPERATURE][1] = hass.config.units.temperature_unit available_sensors = { "DHT11": Adafruit_DHT.DHT11, "DHT22": Adafruit_DHT.DHT22, "AM2302": Adafruit_DHT.AM2302 } - sensor = available_sensors[config['sensor']] - - pin = config['pin'] + sensor = available_sensors.get(config.get(CONF_SENSOR)) + pin = config.get(CONF_PIN) if not sensor or not pin: _LOGGER.error( @@ -101,15 +104,15 @@ class DHTSensor(Entity): self.dht_client.update() data = self.dht_client.data - if self.type == 'temperature': - temperature = round(data['temperature'], 1) + if self.type == SENSOR_TEMPERATURE: + temperature = round(data[SENSOR_TEMPERATURE], 1) if (temperature >= -20) and (temperature < 80): self._state = temperature if self.temp_unit == TEMP_FAHRENHEIT: self._state = round(celsius_to_fahrenheit(temperature), 1) - elif self.type == 'humidity': - humidity = round(data['humidity'], 1) + elif self.type == SENSOR_HUMIDITY: + humidity = round(data[SENSOR_HUMIDITY], 1) if (humidity >= 0) and (humidity <= 100): self._state = humidity @@ -130,6 +133,6 @@ class DHTClient(object): humidity, temperature = self.adafruit_dht.read_retry(self.sensor, self.pin) if temperature: - self.data['temperature'] = temperature + self.data[SENSOR_TEMPERATURE] = temperature if humidity: - self.data['humidity'] = humidity + self.data[SENSOR_HUMIDITY] = humidity From 95b98f67527bfcadc61d92910648c7fbd9c22746 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 26 Aug 2016 10:25:56 +0200 Subject: [PATCH 175/193] Full homematic system variable support (#2986) --- homeassistant/components/homematic.py | 167 +++++++++++++++++++------ homeassistant/components/services.yaml | 12 ++ 2 files changed, 140 insertions(+), 39 deletions(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index 0a0424188c4..d2c19f52920 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -7,24 +7,29 @@ https://home-assistant.io/components/homematic/ import os import time import logging +from datetime import timedelta from functools import partial + import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN, - CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM) + CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM, + ATTR_ENTITY_ID) from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers import discovery from homeassistant.config import load_yaml_config_file +from homeassistant.util import Throttle DOMAIN = 'homematic' REQUIREMENTS = ["pyhomematic==0.1.13"] -ENTITY_ID_FORMAT = DOMAIN + '.{}' - HOMEMATIC = None HOMEMATIC_LINK_DELAY = 0.5 +HOMEMATIC_VAR = {} + +MIN_TIME_BETWEEN_UPDATE_HUB = timedelta(seconds=300) DISCOVER_SWITCHES = 'homematic.switch' DISCOVER_LIGHTS = 'homematic.light' @@ -38,11 +43,13 @@ ATTR_PARAM = 'param' ATTR_CHANNEL = 'channel' ATTR_NAME = 'name' ATTR_ADDRESS = 'address' +ATTR_VALUE = 'value' EVENT_KEYPRESS = 'homematic.keypress' EVENT_IMPULSE = 'homematic.impulse' SERVICE_VIRTUALKEY = 'virtualkey' +SERVICE_SET_VALUE = 'set_value' HM_DEVICE_TYPES = { DISCOVER_SWITCHES: ['Switch', 'SwitchPowermeter'], @@ -132,15 +139,40 @@ SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({ vol.Required(ATTR_PARAM): cv.string, }) +SCHEMA_SERVICE_SET_VALUE = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids, + vol.Required(ATTR_VALUE): vol.Coerce(float), +}) -# pylint: disable=unused-argument + +def virtualkey(hass, address, channel, param): + """Send virtual keypress to homematic controlller.""" + data = { + ATTR_ADDRESS: address, + ATTR_CHANNEL: channel, + ATTR_PARAM: param, + } + + hass.services.call(DOMAIN, SERVICE_VIRTUALKEY, data) + + +def set_value(hass, entity_id, value): + """Change value of homematic system variable.""" + data = { + ATTR_ENTITY_ID: entity_id, + ATTR_VALUE: value, + } + + hass.services.call(DOMAIN, SERVICE_SET_VALUE, data) + + +# pylint: disable=unused-argument,too-many-locals def setup(hass, config): """Setup the Homematic component.""" global HOMEMATIC, HOMEMATIC_LINK_DELAY from pyhomematic import HMConnection component = EntityComponent(_LOGGER, DOMAIN, hass) - hm_hub = HMHub() local_ip = config[DOMAIN].get(CONF_LOCAL_IP) local_port = config[DOMAIN].get(CONF_LOCAL_PORT) @@ -157,12 +189,11 @@ def setup(hass, config): # Create server thread bound_system_callback = partial(_system_callback_handler, hass, config) - bound_event_callback = partial(_event_callback_handler, hm_hub) HOMEMATIC = HMConnection(local=local_ip, localport=local_port, remote=remote_ip, remoteport=remote_port, - eventcallback=bound_event_callback, + eventcallback=_event_callback_handler, systemcallback=bound_system_callback, resolvenames=resolvenames, rpcusername=username, @@ -183,17 +214,50 @@ def setup(hass, config): hass.services.register(DOMAIN, SERVICE_VIRTUALKEY, _hm_service_virtualkey, descriptions[DOMAIN][SERVICE_VIRTUALKEY], - SCHEMA_SERVICE_VIRTUALKEY) + schema=SCHEMA_SERVICE_VIRTUALKEY) + + entities = [] + + ## + # init HM variable + variables = HOMEMATIC.getAllSystemVariables() + if variables is not None: + for key, value in variables.items(): + hm_var = HMVariable(key, value) + HOMEMATIC_VAR.update({key: hm_var}) + entities.append(hm_var) + + # add homematic entites + entities.append(HMHub()) + component.add_entities(entities) + + ## + # register set_value service if exists variables + if not HOMEMATIC_VAR: + return True + + def _service_handle_value(service): + """Set value on homematic variable object.""" + variable_list = component.extract_from_service(service) + + value = service.data[ATTR_VALUE] + + for hm_variable in variable_list: + hm_variable.hm_set(value) + + hass.services.register(DOMAIN, SERVICE_SET_VALUE, + _service_handle_value, + descriptions[DOMAIN][SERVICE_SET_VALUE], + schema=SCHEMA_SERVICE_SET_VALUE) - hm_hub.init_data() - component.add_entities([hm_hub]) return True -def _event_callback_handler(hm_hub, interface_id, address, value_key, value): +def _event_callback_handler(interface_id, address, value_key, value): """Callback handler for events.""" if not address: - hm_hub.update_hm_variable(value_key, value) + if value_key in HOMEMATIC_VAR: + HOMEMATIC_VAR[value_key].hm_update(value) # pylint: disable=too-many-branches @@ -444,7 +508,7 @@ class HMHub(Entity): def __init__(self): """Initialize Homematic hub.""" - self._data = {} + self._state = STATE_UNKNOWN @property def name(self): @@ -454,47 +518,72 @@ class HMHub(Entity): @property def state(self): """Return the state of the entity.""" - state = HOMEMATIC.getServiceMessages() - if state is None: - return STATE_UNKNOWN - - return len(state) + return self._state @property def device_state_attributes(self): """Return device specific state attributes.""" - return self._data + return {} - def init_data(self): - """Init variable to object.""" - hm_var = HOMEMATIC.getAllSystemVariables() - for var, val in hm_var: - self._data[var] = val + @property + def icon(self): + """Return the icon to use in the frontend, if any.""" + return "mdi:gradient" - def update_hm_variable(self, variable, value): - """Update homematic variable from Homematic.""" - if variable not in self._data: + @property + def available(self): + """Return true if device is available.""" + return True if HOMEMATIC is not None else False + + @Throttle(MIN_TIME_BETWEEN_UPDATE_HUB) + def update(self): + """Retrieve latest state.""" + if HOMEMATIC is None: return + state = HOMEMATIC.getServiceMessages() + self._state = STATE_UNKNOWN if state is None else len(state) - # if value have change, update HASS - if self._data[variable] != value: - self._data[variable] = value - self.update_ha_state() + +class HMVariable(Entity): + """The Homematic system variable.""" + + def __init__(self, name, state): + """Initialize Homematic hub.""" + self._state = state + self._name = name + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def state(self): + """Return the state of the entity.""" + return self._state + + @property + def icon(self): + """Return the icon to use in the frontend, if any.""" + return "mdi:code-string" @property def should_poll(self): """Return false. Homematic states are pushed by the XML RPC Server.""" return False - @property - def unit_of_measurement(self): - """Return the unit of measurement of this entity, if any.""" - return '#' + def hm_update(self, value): + """Update variable value from event callback.""" + self._state = value + self.update_ha_state() - @property - def icon(self): - """Return the icon to use in the frontend, if any.""" - return "mdi:gradient" + def hm_set(self, value): + """Set variable on homematic controller.""" + if HOMEMATIC is not None: + HOMEMATIC.setSystemVariable(self._name, value) + + # CCU don't send variable updates from own + self.hm_update(value) class HMDevice(Entity): diff --git a/homeassistant/components/services.yaml b/homeassistant/components/services.yaml index 4cbf2a74867..ac6d9829fc5 100644 --- a/homeassistant/components/services.yaml +++ b/homeassistant/components/services.yaml @@ -73,6 +73,18 @@ homematic: description: Event to send i.e. PRESS_LONG, PRESS_SHORT example: PRESS_LONG + set_value: + description: Set the name of a node. + + fields: + entity_id: + description: Name(s) of entities to set value + example: 'homematic.my_variable' + + value: + description: New value + example: 1 + zwave: add_node: description: Add a new node to the zwave network. Refer to OZW.log for details. From d2bb61ad9e6749e8f78ca3e4268eea808b1923a0 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 26 Aug 2016 12:17:50 +0200 Subject: [PATCH 176/193] Change variable to poll for ccu/homegear (#2987) --- homeassistant/components/homematic.py | 42 ++++++++++----------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index d2c19f52920..c01a6fd2ce4 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -27,9 +27,9 @@ REQUIREMENTS = ["pyhomematic==0.1.13"] HOMEMATIC = None HOMEMATIC_LINK_DELAY = 0.5 -HOMEMATIC_VAR = {} MIN_TIME_BETWEEN_UPDATE_HUB = timedelta(seconds=300) +MIN_TIME_BETWEEN_UPDATE_VAR = timedelta(seconds=60) DISCOVER_SWITCHES = 'homematic.switch' DISCOVER_LIGHTS = 'homematic.light' @@ -141,7 +141,7 @@ SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({ SCHEMA_SERVICE_SET_VALUE = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(ATTR_VALUE): vol.Coerce(float), + vol.Required(ATTR_VALUE): cv.match_all, }) @@ -193,7 +193,6 @@ def setup(hass, config): localport=local_port, remote=remote_ip, remoteport=remote_port, - eventcallback=_event_callback_handler, systemcallback=bound_system_callback, resolvenames=resolvenames, rpcusername=username, @@ -223,9 +222,7 @@ def setup(hass, config): variables = HOMEMATIC.getAllSystemVariables() if variables is not None: for key, value in variables.items(): - hm_var = HMVariable(key, value) - HOMEMATIC_VAR.update({key: hm_var}) - entities.append(hm_var) + entities.append(HMVariable(key, value)) # add homematic entites entities.append(HMHub()) @@ -233,7 +230,7 @@ def setup(hass, config): ## # register set_value service if exists variables - if not HOMEMATIC_VAR: + if not variables: return True def _service_handle_value(service): @@ -253,13 +250,6 @@ def setup(hass, config): return True -def _event_callback_handler(interface_id, address, value_key, value): - """Callback handler for events.""" - if not address: - if value_key in HOMEMATIC_VAR: - HOMEMATIC_VAR[value_key].hm_update(value) - - # pylint: disable=too-many-branches def _system_callback_handler(hass, config, src, *args): """Callback handler.""" @@ -567,23 +557,23 @@ class HMVariable(Entity): """Return the icon to use in the frontend, if any.""" return "mdi:code-string" - @property - def should_poll(self): - """Return false. Homematic states are pushed by the XML RPC Server.""" - return False - - def hm_update(self, value): - """Update variable value from event callback.""" - self._state = value - self.update_ha_state() + @Throttle(MIN_TIME_BETWEEN_UPDATE_VAR) + def update(self): + """Retrieve latest state.""" + if HOMEMATIC is None: + return + self._state = HOMEMATIC.getSystemVariable(self._name) def hm_set(self, value): """Set variable on homematic controller.""" if HOMEMATIC is not None: + if isinstance(self._state, bool): + value = cv.boolean(value) + else: + value = float(value) HOMEMATIC.setSystemVariable(self._name, value) - - # CCU don't send variable updates from own - self.hm_update(value) + self._state = value + self.update_ha_state() class HMDevice(Entity): From 9ab2ac766e74f34f107cff94c7aba6c397cc9888 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 26 Aug 2016 14:48:17 +0200 Subject: [PATCH 177/193] add motion sensor / rewrite ffmpeg binary sensor (#2969) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 * use const flags --- .../components/binary_sensor/ffmpeg.py | 174 ++++++++++++++---- .../components/binary_sensor/services.yaml | 9 + homeassistant/components/camera/ffmpeg.py | 2 +- requirements_all.txt | 2 +- 4 files changed, 151 insertions(+), 36 deletions(-) create mode 100644 homeassistant/components/binary_sensor/services.yaml diff --git a/homeassistant/components/binary_sensor/ffmpeg.py b/homeassistant/components/binary_sensor/ffmpeg.py index 4a59d2693e0..be4d595dcb9 100644 --- a/homeassistant/components/binary_sensor/ffmpeg.py +++ b/homeassistant/components/binary_sensor/ffmpeg.py @@ -5,18 +5,27 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.ffmpeg/ """ import logging +from os import path import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.binary_sensor import (BinarySensorDevice, - PLATFORM_SCHEMA) -from homeassistant.const import EVENT_HOMEASSISTANT_STOP, CONF_NAME + PLATFORM_SCHEMA, DOMAIN) +from homeassistant.config import load_yaml_config_file +from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, CONF_NAME, + ATTR_ENTITY_ID) -REQUIREMENTS = ["ha-ffmpeg==0.7"] +REQUIREMENTS = ["ha-ffmpeg==0.8"] + +SERVICE_RESTART = 'ffmpeg_restart' + +FFMPEG_SENSOR_NOISE = 'noise' +FFMPEG_SENSOR_MOTION = 'motion' MAP_FFMPEG_BIN = [ - 'noise' + FFMPEG_SENSOR_NOISE, + FFMPEG_SENSOR_MOTION ] CONF_TOOL = 'tool' @@ -27,44 +36,140 @@ CONF_OUTPUT = 'output' CONF_PEAK = 'peak' CONF_DURATION = 'duration' CONF_RESET = 'reset' +CONF_CHANGES = 'changes' +CONF_REPEAT = 'repeat' +CONF_REPEAT_TIME = 'repeat_time' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_TOOL): vol.In(MAP_FFMPEG_BIN), vol.Required(CONF_INPUT): cv.string, - vol.Optional(CONF_NAME, default="FFmpeg"): cv.string, vol.Optional(CONF_FFMPEG_BIN, default="ffmpeg"): cv.string, + vol.Optional(CONF_NAME, default="FFmpeg"): cv.string, vol.Optional(CONF_EXTRA_ARGUMENTS): cv.string, vol.Optional(CONF_OUTPUT): cv.string, vol.Optional(CONF_PEAK, default=-30): vol.Coerce(int), vol.Optional(CONF_DURATION, default=1): vol.All(vol.Coerce(int), vol.Range(min=1)), - vol.Optional(CONF_RESET, default=2): + vol.Optional(CONF_RESET, default=10): vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_CHANGES, default=10): + vol.All(vol.Coerce(float), vol.Range(min=0, max=99)), + vol.Optional(CONF_REPEAT, default=0): + vol.All(vol.Coerce(int), vol.Range(min=0)), + vol.Optional(CONF_REPEAT_TIME, default=0): + vol.All(vol.Coerce(int), vol.Range(min=0)), }) +SERVICE_RESTART_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, +}) + + +# list of all ffmpeg sensors +DEVICES = [] + _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_entities, discovery_info=None): """Create the binary sensor.""" - if config.get(CONF_TOOL) == "noise": - entity = FFmpegNoise(config) + from haffmpeg import SensorNoise, SensorMotion + + if config.get(CONF_TOOL) == FFMPEG_SENSOR_NOISE: + entity = FFmpegNoise(SensorNoise, config) + else: + entity = FFmpegMotion(SensorMotion, config) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, entity.shutdown_ffmpeg) + + # add to system add_entities([entity]) + DEVICES.append(entity) + + # exists service? + if hass.services.has_service(DOMAIN, SERVICE_RESTART): + return True + + descriptions = load_yaml_config_file( + path.join(path.dirname(__file__), 'services.yaml')) + + # register service + def _service_handle_restart(service): + """Handle service binary_sensor.ffmpeg_restart.""" + entity_ids = service.data.get('entity_id') + + if entity_ids: + _devices = [device for device in DEVICES + if device.entity_id in entity_ids] + else: + _devices = DEVICES + + for device in _devices: + device.reset_ffmpeg() + + hass.services.register(DOMAIN, SERVICE_RESTART, + _service_handle_restart, + descriptions.get(SERVICE_RESTART), + schema=SERVICE_RESTART_SCHEMA) + return True -class FFmpegNoise(BinarySensorDevice): +class FFmpegBinarySensor(BinarySensorDevice): """A binary sensor which use ffmpeg for noise detection.""" - def __init__(self, config): + def __init__(self, ffobj, config): """Constructor for binary sensor noise detection.""" - from haffmpeg import SensorNoise - self._state = False + self._config = config self._name = config.get(CONF_NAME) - self._ffmpeg = SensorNoise(config.get(CONF_FFMPEG_BIN), self._callback) + self._ffmpeg = ffobj(config.get(CONF_FFMPEG_BIN), self._callback) + self._start_ffmpeg(config) + + def _callback(self, state): + """HA-FFmpeg callback for noise detection.""" + self._state = state + self.update_ha_state() + + def _start_ffmpeg(self, config): + """Start a FFmpeg instance.""" + raise NotImplementedError + + def shutdown_ffmpeg(self, event): + """For STOP event to shutdown ffmpeg.""" + self._ffmpeg.close() + + def reset_ffmpeg(self): + """Restart ffmpeg with new config.""" + self._ffmpeg.close() + self._start_ffmpeg(self._config) + + @property + def is_on(self): + """True if the binary sensor is on.""" + return self._state + + @property + def should_poll(self): + """Return True if entity has to be polled for state.""" + return False + + @property + def name(self): + """Return the name of the entity.""" + return self._name + + @property + def available(self): + """Return True if entity is available.""" + return self._ffmpeg.is_running + + +class FFmpegNoise(FFmpegBinarySensor): + """A binary sensor which use ffmpeg for noise detection.""" + + def _start_ffmpeg(self, config): + """Start a FFmpeg instance.""" # init config self._ffmpeg.set_options( time_duration=config.get(CONF_DURATION), @@ -79,31 +184,32 @@ class FFmpegNoise(BinarySensorDevice): extra_cmd=config.get(CONF_EXTRA_ARGUMENTS), ) - def _callback(self, state): - """HA-FFmpeg callback for noise detection.""" - self._state = state - self.update_ha_state() - - def shutdown_ffmpeg(self, event): - """For STOP event to shutdown ffmpeg.""" - self._ffmpeg.close() - - @property - def is_on(self): - """True if the binary sensor is on.""" - return self._state - @property def sensor_class(self): """Return the class of this sensor, from SENSOR_CLASSES.""" return "sound" - @property - def should_poll(self): - """Return True if entity has to be polled for state.""" - return False + +class FFmpegMotion(FFmpegBinarySensor): + """A binary sensor which use ffmpeg for noise detection.""" + + def _start_ffmpeg(self, config): + """Start a FFmpeg instance.""" + # init config + self._ffmpeg.set_options( + time_reset=config.get(CONF_RESET), + time_repeat=config.get(CONF_REPEAT_TIME), + repeat=config.get(CONF_REPEAT), + changes=config.get(CONF_CHANGES), + ) + + # run + self._ffmpeg.open_sensor( + input_source=config.get(CONF_INPUT), + extra_cmd=config.get(CONF_EXTRA_ARGUMENTS), + ) @property - def name(self): - """Return the name of the entity.""" - return self._name + def sensor_class(self): + """Return the class of this sensor, from SENSOR_CLASSES.""" + return "motion" diff --git a/homeassistant/components/binary_sensor/services.yaml b/homeassistant/components/binary_sensor/services.yaml new file mode 100644 index 00000000000..9be9915e268 --- /dev/null +++ b/homeassistant/components/binary_sensor/services.yaml @@ -0,0 +1,9 @@ +# Describes the format for available binary_sensor services + +ffmpeg_restart: + description: Send a restart command to a ffmpeg based sensor (party mode). + + fields: + entity_id: + description: Name(s) of entites that will restart. Platform dependent. + example: 'binary_sensor.ffmpeg_noise' diff --git a/homeassistant/components/camera/ffmpeg.py b/homeassistant/components/camera/ffmpeg.py index d5055e942e7..1eaabc45195 100644 --- a/homeassistant/components/camera/ffmpeg.py +++ b/homeassistant/components/camera/ffmpeg.py @@ -14,7 +14,7 @@ from homeassistant.components.camera.mjpeg import extract_image_from_mjpeg import homeassistant.helpers.config_validation as cv from homeassistant.const import CONF_NAME, CONF_PLATFORM -REQUIREMENTS = ["ha-ffmpeg==0.7"] +REQUIREMENTS = ["ha-ffmpeg==0.8"] CONF_INPUT = 'input' CONF_FFMPEG_BIN = 'ffmpeg_bin' diff --git a/requirements_all.txt b/requirements_all.txt index fd16391f6e6..8b95fe4541c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -104,7 +104,7 @@ gps3==0.33.2 # homeassistant.components.binary_sensor.ffmpeg # homeassistant.components.camera.ffmpeg -ha-ffmpeg==0.7 +ha-ffmpeg==0.8 # homeassistant.components.mqtt.server hbmqtt==0.7.1 From 4ee37cb8c8058628b4396cadf4236459e822af75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Sandstr=C3=B6m?= Date: Fri, 26 Aug 2016 21:38:49 +0200 Subject: [PATCH 178/193] bump vsure version --- homeassistant/components/verisure.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/verisure.py b/homeassistant/components/verisure.py index 901b577a9a0..1231a4128fa 100644 --- a/homeassistant/components/verisure.py +++ b/homeassistant/components/verisure.py @@ -15,7 +15,7 @@ from homeassistant.util import Throttle DOMAIN = "verisure" -REQUIREMENTS = ['vsure==0.10.1'] +REQUIREMENTS = ['vsure==0.10.2'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 8b95fe4541c..5d561940d3a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -480,7 +480,7 @@ urllib3 uvcclient==0.9.0 # homeassistant.components.verisure -vsure==0.10.1 +vsure==0.10.2 # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 From 5cc672ea599f9109bb84c1be5b72eb219c009494 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 26 Aug 2016 22:50:32 +0200 Subject: [PATCH 179/193] Migrate to voluptuous (#2990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- homeassistant/components/camera/bloomsky.py | 12 ++++----- homeassistant/components/camera/netatmo.py | 27 ++++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/camera/bloomsky.py b/homeassistant/components/camera/bloomsky.py index cd40b91a21c..7137c73c299 100644 --- a/homeassistant/components/camera/bloomsky.py +++ b/homeassistant/components/camera/bloomsky.py @@ -11,15 +11,15 @@ import requests from homeassistant.components.camera import Camera from homeassistant.loader import get_component -DEPENDENCIES = ["bloomsky"] +DEPENDENCIES = ['bloomsky'] # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup access to BloomSky cameras.""" bloomsky = get_component('bloomsky') for device in bloomsky.BLOOMSKY.devices.values(): - add_devices_callback([BloomSkyCamera(bloomsky.BLOOMSKY, device)]) + add_devices([BloomSkyCamera(bloomsky.BLOOMSKY, device)]) class BloomSkyCamera(Camera): @@ -28,8 +28,8 @@ class BloomSkyCamera(Camera): def __init__(self, bs, device): """Setup for access to the BloomSky camera images.""" super(BloomSkyCamera, self).__init__() - self._name = device["DeviceName"] - self._id = device["DeviceID"] + self._name = device['DeviceName'] + self._id = device['DeviceID'] self._bloomsky = bs self._url = "" self._last_url = "" @@ -42,7 +42,7 @@ class BloomSkyCamera(Camera): def camera_image(self): """Update the camera's image if it has changed.""" try: - self._url = self._bloomsky.devices[self._id]["Data"]["ImageURL"] + self._url = self._bloomsky.devices[self._id]['Data']['ImageURL'] self._bloomsky.refresh_devices() # If the URL hasn't changed then the image hasn't changed. if self._url != self._last_url: diff --git a/homeassistant/components/camera/netatmo.py b/homeassistant/components/camera/netatmo.py index 8462d4597dd..457c63d1ad7 100644 --- a/homeassistant/components/camera/netatmo.py +++ b/homeassistant/components/camera/netatmo.py @@ -6,34 +6,43 @@ https://home-assistant.io/components/camera.netatmo/ """ import logging from datetime import timedelta + import requests +import voluptuous as vol + from homeassistant.util import Throttle - -from homeassistant.components.camera import Camera +from homeassistant.components.camera import (Camera, PLATFORM_SCHEMA) from homeassistant.loader import get_component +from homeassistant.helpers import config_validation as cv -DEPENDENCIES = ["netatmo"] +DEPENDENCIES = ['netatmo'] _LOGGER = logging.getLogger(__name__) CONF_HOME = 'home' -ATTR_CAMERAS = 'cameras' +CONF_CAMERAS = 'cameras' MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10) +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_HOME): cv.string, + vol.Optional(CONF_CAMERAS, default=[]): + vol.All(cv.ensure_list, [cv.string]), +}) + # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup access to Netatmo Welcome cameras.""" netatmo = get_component('netatmo') - home = config.get(CONF_HOME, None) + home = config.get(CONF_HOME) data = WelcomeData(netatmo.NETATMO_AUTH, home) for camera_name in data.get_camera_names(): - if ATTR_CAMERAS in config: - if camera_name not in config[ATTR_CAMERAS]: + if CONF_CAMERAS in config: + if camera_name not in config[CONF_CAMERAS]: continue - add_devices_callback([WelcomeCamera(data, camera_name, home)]) + add_devices([WelcomeCamera(data, camera_name, home)]) class WelcomeCamera(Camera): From 37048919bfe5eb69137e4e9f325858065f8078fe Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Sat, 27 Aug 2016 01:33:57 +0200 Subject: [PATCH 180/193] Check config requirement fix (#2999) * Check config requirement fix --- homeassistant/scripts/check_config.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index 23e9766928e..624452b0592 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -13,7 +13,7 @@ import homeassistant.config as config_util import homeassistant.loader as loader import homeassistant.util.yaml as yaml -REQUIREMENTS = ('colorlog>2.1<3',) +REQUIREMENTS = ('colorlog>2.1,<3',) if system() == 'Windows': # Ensure colorama installed for colorlog on Windows REQUIREMENTS += ('colorama<=1',) @@ -116,7 +116,7 @@ def run(script_args: List) -> int: if 'all' in domain_info: print(color('bold_white', 'Successful config (all)')) for domain, config in res['components'].items(): - print(color(C_HEAD, domain + ':')) + print(' ', color(C_HEAD, domain + ':')) dump_dict(config, indent_count=3) else: print(color('bold_white', 'Successful config (partial)')) diff --git a/requirements_all.txt b/requirements_all.txt index 5d561940d3a..f19f22813f2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -53,7 +53,7 @@ boto3==1.3.1 cherrypy==7.1.0 # homeassistant.scripts.check_config -colorlog>2.1<3 +colorlog>2.1,<3 # homeassistant.components.media_player.directv directpy==0.1 From 4aad83d60b7f7ea02420ec546626a5c979442449 Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Sat, 27 Aug 2016 02:43:59 +0200 Subject: [PATCH 181/193] Voluptuous for pushover (#3000) --- homeassistant/components/notify/pushover.py | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/notify/pushover.py b/homeassistant/components/notify/pushover.py index a8bc3cf5179..5ded1ebe778 100644 --- a/homeassistant/components/notify/pushover.py +++ b/homeassistant/components/notify/pushover.py @@ -6,23 +6,26 @@ https://home-assistant.io/components/notify.pushover/ """ import logging +import voluptuous as vol + from homeassistant.components.notify import ( - ATTR_TITLE, ATTR_TARGET, ATTR_DATA, DOMAIN, BaseNotificationService) + ATTR_TITLE, ATTR_TARGET, ATTR_DATA, BaseNotificationService) from homeassistant.const import CONF_API_KEY -from homeassistant.helpers import validate_config +import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['python-pushover==0.2'] _LOGGER = logging.getLogger(__name__) +PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ + vol.Required('user_key'): cv.string, + vol.Required(CONF_API_KEY): cv.string, +}) + + # pylint: disable=unused-variable def get_service(hass, config): """Get the Pushover notification service.""" - if not validate_config({DOMAIN: config}, - {DOMAIN: ['user_key', CONF_API_KEY]}, - _LOGGER): - return None - from pushover import InitError try: @@ -30,8 +33,7 @@ def get_service(hass, config): config[CONF_API_KEY]) except InitError: _LOGGER.error( - "Wrong API key supplied. " - "Get it at https://pushover.net") + 'Wrong API key supplied. Get it at https://pushover.net') return None @@ -47,7 +49,7 @@ class PushoverNotificationService(BaseNotificationService): self.pushover = Client( self._user_key, api_token=self._api_token) - def send_message(self, message="", **kwargs): + def send_message(self, message='', **kwargs): """Send a message to a user.""" from pushover import RequestError @@ -65,4 +67,4 @@ class PushoverNotificationService(BaseNotificationService): except ValueError as val_err: _LOGGER.error(str(val_err)) except RequestError: - _LOGGER.exception("Could not send pushover notification") + _LOGGER.exception('Could not send pushover notification') From a4b8c3cab0b3e3a7613924492535c13cd39d3114 Mon Sep 17 00:00:00 2001 From: icovada Date: Sat, 27 Aug 2016 02:52:44 +0200 Subject: [PATCH 182/193] Update telegram.py add send_document (#2937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- homeassistant/components/notify/telegram.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/homeassistant/components/notify/telegram.py b/homeassistant/components/notify/telegram.py index 5e0cee9a441..8da916eb1f3 100644 --- a/homeassistant/components/notify/telegram.py +++ b/homeassistant/components/notify/telegram.py @@ -21,6 +21,7 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['python-telegram-bot==5.0.0'] ATTR_PHOTO = "photo" +ATTR_DOCUMENT = "document" ATTR_CAPTION = "caption" CONF_CHAT_ID = 'chat_id' @@ -102,6 +103,8 @@ class TelegramNotificationService(BaseNotificationService): return elif data is not None and ATTR_LOCATION in data: return self.send_location(data.get(ATTR_LOCATION)) + elif data is not None and ATTR_DOCUMENT in data: + return self.send_document(data.get(ATTR_DOCUMENT)) # send message try: @@ -125,6 +128,20 @@ class TelegramNotificationService(BaseNotificationService): _LOGGER.exception("Error sending photo.") return + def send_document(self, data): + """Send a document.""" + import telegram + caption = data.pop(ATTR_CAPTION, None) + + # send photo + try: + document = load_data(**data) + self.bot.sendDocument(chat_id=self._chat_id, + document=document, caption=caption) + except telegram.error.TelegramError: + _LOGGER.exception("Error sending document.") + return + def send_location(self, gps): """Send a location.""" import telegram From c05d27d2142bdaaf5df199a1d33023a4ab1c849f Mon Sep 17 00:00:00 2001 From: Matthew Bowen Date: Sat, 27 Aug 2016 04:23:40 -0400 Subject: [PATCH 183/193] Completely local control of entities via Alexa (#2942) * Initial code for alexa_local_control. * Added support for creating a dummy username. * Move SSDP responses to local variables. * Added config validation via Voluptuous. * Modify and remove unnecessary returned emulated bridge values. * Remove script and scene domains from default exposed domains. * Replaced Flask with HomeAssistantWSGI. * Fix lint errors. * Correcting grammar and spelling in docs and comments. * Rename alexa_local_control to emulated_hue. * Rename emulated_hue attributes. * Fix a bug where something marked not exposed is exposed by default. * Make sure the UPNP responder thread cleanly stops when HASS stops. Also fix some config loading and lint errors. * Fixed unexposed entities still having individual state exposed. * Started writing tests for emulated_hue. * Fix being able to set state of non-exposed entity. * Another test for emulated_hue. * More tests for emulated_hue. Also slightly simplified emulated_hue's PUT handler. * Fix bad test, sorry :/ * Third time's the charm. * Fix lint and value validation tests. * Rename emulated_hue bridge name. * Remove license and documentation from header. * Combine two if statements. * Style changes. * Fixed various issues and added some constants --- homeassistant/components/emulated_hue.py | 542 +++++++++++++++++++++++ tests/components/test_emulated_hue.py | 445 +++++++++++++++++++ 2 files changed, 987 insertions(+) create mode 100755 homeassistant/components/emulated_hue.py create mode 100755 tests/components/test_emulated_hue.py diff --git a/homeassistant/components/emulated_hue.py b/homeassistant/components/emulated_hue.py new file mode 100755 index 00000000000..f7a353d5c7f --- /dev/null +++ b/homeassistant/components/emulated_hue.py @@ -0,0 +1,542 @@ +""" +Support for local control of entities by emulating the Phillips Hue bridge. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/emulated_hue/ +""" +import threading +import socket +import logging +import json +import os +import select + +import voluptuous as vol + +from homeassistant import util, core +from homeassistant.const import ( + ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, + EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, + STATE_ON +) +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS +) +from homeassistant.components.http import ( + HomeAssistantView, HomeAssistantWSGI +) +import homeassistant.helpers.config_validation as cv + +DOMAIN = 'emulated_hue' + +_LOGGER = logging.getLogger(__name__) + +CONF_HOST_IP = 'host_ip' +CONF_LISTEN_PORT = 'listen_port' +CONF_OFF_MAPS_TO_ON_DOMAINS = 'off_maps_to_on_domains' +CONF_EXPOSE_BY_DEFAULT = 'expose_by_default' +CONF_EXPOSED_DOMAINS = 'exposed_domains' + +ATTR_EMULATED_HUE = 'emulated_hue' +ATTR_EMULATED_HUE_NAME = 'emulated_hue_name' + +DEFAULT_LISTEN_PORT = 8300 +DEFAULT_OFF_MAPS_TO_ON_DOMAINS = ['script', 'scene'] +DEFAULT_EXPOSE_BY_DEFAULT = True +DEFAULT_EXPOSED_DOMAINS = [ + 'switch', 'light', 'group', 'input_boolean', 'media_player' +] + +HUE_API_STATE_ON = 'on' +HUE_API_STATE_BRI = 'bri' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_HOST_IP): cv.string, + vol.Optional(CONF_LISTEN_PORT, default=DEFAULT_LISTEN_PORT): + vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + vol.Optional(CONF_OFF_MAPS_TO_ON_DOMAINS): cv.ensure_list, + vol.Optional(CONF_EXPOSE_BY_DEFAULT): cv.boolean, + vol.Optional(CONF_EXPOSED_DOMAINS): cv.ensure_list + }) +}, extra=vol.ALLOW_EXTRA) + + +def setup(hass, yaml_config): + """Activate the emulated_hue component.""" + config = Config(yaml_config) + + server = HomeAssistantWSGI( + hass, + development=False, + server_host=config.host_ip_addr, + server_port=config.listen_port, + api_password=None, + ssl_certificate=None, + ssl_key=None, + cors_origins=[] + ) + + server.register_view(DescriptionXmlView(hass, config)) + server.register_view(HueUsernameView(hass)) + server.register_view(HueLightsView(hass, config)) + + upnp_listener = UPNPResponderThread( + config.host_ip_addr, config.listen_port) + + def start_emulated_hue_bridge(event): + """Start the emulated hue bridge.""" + server.start() + upnp_listener.start() + + hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_emulated_hue_bridge) + + def stop_emulated_hue_bridge(event): + """Stop the emulated hue bridge.""" + upnp_listener.stop() + server.stop() + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_emulated_hue_bridge) + + return True + + +# pylint: disable=too-few-public-methods +class Config(object): + """Holds configuration variables for the emulated hue bridge.""" + + def __init__(self, yaml_config): + """Initialize the instance.""" + conf = yaml_config.get(DOMAIN, {}) + + # Get the IP address that will be passed to the Echo during discovery + self.host_ip_addr = conf.get(CONF_HOST_IP) + if self.host_ip_addr is None: + self.host_ip_addr = util.get_local_ip() + _LOGGER.warning( + "Listen IP address not specified, auto-detected address is %s", + self.host_ip_addr) + + # Get the port that the Hue bridge will listen on + self.listen_port = conf.get(CONF_LISTEN_PORT) + if not isinstance(self.listen_port, int): + self.listen_port = DEFAULT_LISTEN_PORT + _LOGGER.warning( + "Listen port not specified, defaulting to %s", + self.listen_port) + + # Get domains that cause both "on" and "off" commands to map to "on" + # This is primarily useful for things like scenes or scripts, which + # don't really have a concept of being off + self.off_maps_to_on_domains = conf.get(CONF_OFF_MAPS_TO_ON_DOMAINS) + if not isinstance(self.off_maps_to_on_domains, list): + self.off_maps_to_on_domains = DEFAULT_OFF_MAPS_TO_ON_DOMAINS + + # Get whether or not entities should be exposed by default, or if only + # explicitly marked ones will be exposed + self.expose_by_default = conf.get( + CONF_EXPOSE_BY_DEFAULT, DEFAULT_EXPOSE_BY_DEFAULT) + + # Get domains that are exposed by default when expose_by_default is + # True + self.exposed_domains = conf.get( + CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS) + + +class DescriptionXmlView(HomeAssistantView): + """Handles requests for the description.xml file.""" + + url = '/description.xml' + name = 'description:xml' + requires_auth = False + + def __init__(self, hass, config): + """Initialize the instance of the view.""" + super().__init__(hass) + self.config = config + + def get(self, request): + """Handle a GET request.""" + xml_template = """ + + +1 +0 + +http://{0}:{1}/ + +urn:schemas-upnp-org:device:Basic:1 +HASS Bridge ({0}) +Royal Philips Electronics +http://www.philips.com +Philips hue Personal Wireless Lighting +Philips hue bridge 2015 +BSB002 +http://www.meethue.com +1234 +uuid:2f402f80-da50-11e1-9b23-001788255acc + + +""" + + resp_text = xml_template.format( + self.config.host_ip_addr, self.config.listen_port) + + return self.Response(resp_text, mimetype='text/xml') + + +class HueUsernameView(HomeAssistantView): + """Handle requests to create a username for the emulated hue bridge.""" + + url = '/api' + name = 'hue:api' + requires_auth = False + + def __init__(self, hass): + """Initialize the instance of the view.""" + super().__init__(hass) + + def post(self, request): + """Handle a POST request.""" + data = request.json + + if 'devicetype' not in data: + return self.Response("devicetype not specified", status=400) + + json_response = [{'success': {'username': '12345678901234567890'}}] + + return self.json(json_response) + + +class HueLightsView(HomeAssistantView): + """Handle requests for getting and setting info about entities.""" + + url = '/api//lights' + name = 'api:username:lights' + extra_urls = ['/api//lights/', + '/api//lights//state'] + requires_auth = False + + def __init__(self, hass, config): + """Initialize the instance of the view.""" + super().__init__(hass) + self.config = config + self.cached_states = {} + + def get(self, request, username, entity_id=None): + """Handle a GET request.""" + if entity_id is None: + return self.get_lights_list() + + if not request.base_url.endswith('state'): + return self.get_light_state(entity_id) + + return self.Response("Method not allowed", status=405) + + def put(self, request, username, entity_id=None): + """Handle a PUT request.""" + if not request.base_url.endswith('state'): + return self.Response("Method not allowed", status=405) + + content_type = request.environ.get('CONTENT_TYPE', '') + if content_type == 'application/x-www-form-urlencoded': + # Alexa sends JSON data with a form data content type, for + # whatever reason, and Werkzeug parses form data automatically, + # so we need to do some gymnastics to get the data we need + json_data = None + + for key in request.form: + try: + json_data = json.loads(key) + break + except ValueError: + # Try the next key? + pass + + if json_data is None: + return self.Response("Bad request", status=400) + else: + json_data = request.json + + return self.put_light_state(json_data, entity_id) + + def get_lights_list(self): + """Process a request to get the list of available lights.""" + json_response = {} + + for entity in self.hass.states.all(): + if self.is_entity_exposed(entity): + json_response[entity.entity_id] = entity_to_json(entity) + + return self.json(json_response) + + def get_light_state(self, entity_id): + """Process a request to get the state of an individual light.""" + entity = self.hass.states.get(entity_id) + if entity is None or not self.is_entity_exposed(entity): + return self.Response("Entity not found", status=404) + + cached_state = self.cached_states.get(entity_id, None) + + if cached_state is None: + final_state = entity.state == STATE_ON + final_brightness = entity.attributes.get( + ATTR_BRIGHTNESS, 255 if final_state else 0) + else: + final_state, final_brightness = cached_state + + json_response = entity_to_json(entity, final_state, final_brightness) + + return self.json(json_response) + + def put_light_state(self, request_json, entity_id): + """Process a request to set the state of an individual light.""" + config = self.config + + # Retrieve the entity from the state machine + entity = self.hass.states.get(entity_id) + if entity is None: + return self.Response("Entity not found", status=404) + + if not self.is_entity_exposed(entity): + return self.Response("Entity not found", status=404) + + # Parse the request into requested "on" status and brightness + parsed = parse_hue_api_put_light_body(request_json, entity) + + if parsed is None: + return self.Response("Bad request", status=400) + + result, brightness = parsed + + # Convert the resulting "on" status into the service we need to call + service = SERVICE_TURN_ON if result else SERVICE_TURN_OFF + + # Construct what we need to send to the service + data = {ATTR_ENTITY_ID: entity_id} + + if brightness is not None: + data[ATTR_BRIGHTNESS] = brightness + + if entity.domain.lower() in config.off_maps_to_on_domains: + # Map the off command to on + service = SERVICE_TURN_ON + + # Caching is required because things like scripts and scenes won't + # report as "off" to Alexa if an "off" command is received, because + # they'll map to "on". Thus, instead of reporting its actual + # status, we report what Alexa will want to see, which is the same + # as the actual requested command. + self.cached_states[entity_id] = (result, brightness) + + # Perform the requested action + self.hass.services.call(core.DOMAIN, service, data, blocking=True) + + json_response = \ + [create_hue_success_response(entity_id, HUE_API_STATE_ON, result)] + + if brightness is not None: + json_response.append(create_hue_success_response( + entity_id, HUE_API_STATE_BRI, brightness)) + + return self.json(json_response) + + def is_entity_exposed(self, entity): + """Determine if an entity should be exposed on the emulated bridge.""" + config = self.config + + if entity.attributes.get('view') is not None: + # Ignore entities that are views + return False + + domain = entity.domain.lower() + explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None) + + domain_exposed_by_default = \ + config.expose_by_default and domain in config.exposed_domains + + # Expose an entity if the entity's domain is exposed by default and + # the configuration doesn't explicitly exclude it from being + # exposed, or if the entity is explicitly exposed + is_default_exposed = \ + domain_exposed_by_default and explicit_expose is not False + + return is_default_exposed or explicit_expose + + +def parse_hue_api_put_light_body(request_json, entity): + """Parse the body of a request to change the state of a light.""" + if HUE_API_STATE_ON in request_json: + if not isinstance(request_json[HUE_API_STATE_ON], bool): + return None + + if request_json['on']: + # Echo requested device be turned on + brightness = None + report_brightness = False + result = True + else: + # Echo requested device be turned off + brightness = None + report_brightness = False + result = False + + if HUE_API_STATE_BRI in request_json: + # Make sure the entity actually supports brightness + entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + + if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: + try: + # Clamp brightness from 0 to 255 + brightness = \ + max(0, min(int(request_json[HUE_API_STATE_BRI]), 255)) + except ValueError: + return None + + report_brightness = True + result = (brightness > 0) + + return (result, brightness) if report_brightness else (result, None) + + +def entity_to_json(entity, is_on=None, brightness=None): + """Convert an entity to its Hue bridge JSON representation.""" + if is_on is None: + is_on = entity.state == STATE_ON + + if brightness is None: + brightness = 255 if is_on else 0 + + name = entity.attributes.get( + ATTR_EMULATED_HUE_NAME, entity.attributes[ATTR_FRIENDLY_NAME]) + + return { + 'state': + { + HUE_API_STATE_ON: is_on, + HUE_API_STATE_BRI: brightness, + 'reachable': True + }, + 'type': 'Dimmable light', + 'name': name, + 'modelid': 'HASS123', + 'uniqueid': entity.entity_id, + 'swversion': '123' + } + + +def create_hue_success_response(entity_id, attr, value): + """Create a success response for an attribute set on a light.""" + success_key = '/lights/{}/state/{}'.format(entity_id, attr) + return {'success': {success_key: value}} + + +class UPNPResponderThread(threading.Thread): + """Handle responding to UPNP/SSDP discovery requests.""" + + _interrupted = False + + def __init__(self, host_ip_addr, listen_port): + """Initialize the class.""" + threading.Thread.__init__(self) + + self.host_ip_addr = host_ip_addr + self.listen_port = listen_port + + # Note that the double newline at the end of + # this string is required per the SSDP spec + resp_template = """HTTP/1.1 200 OK +CACHE-CONTROL: max-age=60 +EXT: +LOCATION: http://{0}:{1}/description.xml +SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1 +ST: urn:schemas-upnp-org:device:basic:1 +USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1 + +""" + + self.upnp_response = resp_template.format(host_ip_addr, listen_port) \ + .replace("\n", "\r\n") \ + .encode('utf-8') + + # Set up a pipe for signaling to the receiver that it's time to + # shutdown. Essentially, we place the SSDP socket into nonblocking + # mode and use select() to wait for data to arrive on either the SSDP + # socket or the pipe. If data arrives on either one, select() returns + # and tells us which filenos have data ready to read. + # + # When we want to stop the responder, we write data to the pipe, which + # causes the select() to return and indicate that said pipe has data + # ready to be read, which indicates to us that the responder needs to + # be shutdown. + self._interrupted_read_pipe, self._interrupted_write_pipe = os.pipe() + + def run(self): + """Run the server.""" + # Listen for UDP port 1900 packets sent to SSDP multicast address + ssdp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + ssdp_socket.setblocking(False) + + # Required for receiving multicast + ssdp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + ssdp_socket.setsockopt( + socket.SOL_IP, + socket.IP_MULTICAST_IF, + socket.inet_aton(self.host_ip_addr)) + + ssdp_socket.setsockopt( + socket.SOL_IP, + socket.IP_ADD_MEMBERSHIP, + socket.inet_aton("239.255.255.250") + + socket.inet_aton(self.host_ip_addr)) + + ssdp_socket.bind(("239.255.255.250", 1900)) + + while True: + if self._interrupted: + clean_socket_close(ssdp_socket) + return + + try: + read, _, _ = select.select( + [self._interrupted_read_pipe, ssdp_socket], [], + [ssdp_socket]) + + if self._interrupted_read_pipe in read: + # Implies self._interrupted is True + clean_socket_close(ssdp_socket) + return + elif ssdp_socket in read: + data, addr = ssdp_socket.recvfrom(1024) + else: + continue + except socket.error as ex: + if self._interrupted: + clean_socket_close(ssdp_socket) + return + + _LOGGER.error("UPNP Responder socket exception occured: %s", + ex.__str__) + + if "M-SEARCH" in data.decode('utf-8'): + # SSDP M-SEARCH method received, respond to it with our info + resp_socket = socket.socket( + socket.AF_INET, socket.SOCK_DGRAM) + + resp_socket.sendto(self.upnp_response, addr) + resp_socket.close() + + def stop(self): + """Stop the server.""" + # Request for server + self._interrupted = True + os.write(self._interrupted_write_pipe, bytes([0])) + self.join() + + +def clean_socket_close(sock): + """Close a socket connection and logs its closure.""" + _LOGGER.info("UPNP responder shutting down.") + + sock.close() diff --git a/tests/components/test_emulated_hue.py b/tests/components/test_emulated_hue.py new file mode 100755 index 00000000000..c9efa6e9fda --- /dev/null +++ b/tests/components/test_emulated_hue.py @@ -0,0 +1,445 @@ +import time +import json +import threading +import asyncio + +import unittest +import requests + +from homeassistant import bootstrap, const, core +import homeassistant.components as core_components +from homeassistant.components import emulated_hue, http, light, mqtt +from homeassistant.const import STATE_ON, STATE_OFF +from homeassistant.components.emulated_hue import ( + HUE_API_STATE_ON, HUE_API_STATE_BRI +) + +from tests.common import get_test_instance_port, get_test_home_assistant + +HTTP_SERVER_PORT = get_test_instance_port() +BRIDGE_SERVER_PORT = get_test_instance_port() +MQTT_BROKER_PORT = get_test_instance_port() + +BRIDGE_URL_BASE = "http://127.0.0.1:{}".format(BRIDGE_SERVER_PORT) + "{}" +JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON} + +mqtt_broker = None + + +def setUpModule(): + global mqtt_broker + + mqtt_broker = MQTTBroker('127.0.0.1', MQTT_BROKER_PORT) + mqtt_broker.start() + + +def tearDownModule(): + global mqtt_broker + + mqtt_broker.stop() + + +def setup_hass_instance(emulated_hue_config): + hass = get_test_home_assistant() + + # We need to do this to get access to homeassistant/turn_(on,off) + core_components.setup(hass, {core.DOMAIN: {}}) + + bootstrap.setup_component( + hass, http.DOMAIN, + {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}) + + bootstrap.setup_component(hass, emulated_hue.DOMAIN, emulated_hue_config) + + return hass + + +def start_hass_instance(hass): + hass.start() + time.sleep(0.05) + + +class TestEmulatedHue(unittest.TestCase): + hass = None + + @classmethod + def setUpClass(cls): + cls.hass = setup_hass_instance({ + emulated_hue.DOMAIN: { + emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT + }}) + + start_hass_instance(cls.hass) + + @classmethod + def tearDownClass(cls): + cls.hass.stop() + + def test_description_xml(self): + import xml.etree.ElementTree as ET + + result = requests.get( + BRIDGE_URL_BASE.format('/description.xml'), timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('text/xml' in result.headers['content-type']) + + # Make sure the XML is parsable + try: + ET.fromstring(result.text) + except: + self.fail('description.xml is not valid XML!') + + def test_create_username(self): + request_json = {'devicetype': 'my_device'} + + result = requests.post( + BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), + timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('application/json' in result.headers['content-type']) + + resp_json = result.json() + success_json = resp_json[0] + + self.assertTrue('success' in success_json) + self.assertTrue('username' in success_json['success']) + + def test_valid_username_request(self): + request_json = {'invalid_key': 'my_device'} + + result = requests.post( + BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), + timeout=5) + + self.assertEqual(result.status_code, 400) + + +class TestEmulatedHueExposedByDefault(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.hass = setup_hass_instance({ + emulated_hue.DOMAIN: { + emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT, + emulated_hue.CONF_EXPOSE_BY_DEFAULT: True + } + }) + + bootstrap.setup_component(cls.hass, mqtt.DOMAIN, { + 'mqtt': { + 'broker': '127.0.0.1', + 'port': MQTT_BROKER_PORT + } + }) + + bootstrap.setup_component(cls.hass, light.DOMAIN, { + 'light': [ + { + 'platform': 'mqtt', + 'name': 'Office light', + 'state_topic': 'office/rgb1/light/status', + 'command_topic': 'office/rgb1/light/switch', + 'brightness_state_topic': 'office/rgb1/brightness/status', + 'brightness_command_topic': 'office/rgb1/brightness/set', + 'optimistic': True + }, + { + 'platform': 'mqtt', + 'name': 'Bedroom light', + 'state_topic': 'bedroom/rgb1/light/status', + 'command_topic': 'bedroom/rgb1/light/switch', + 'brightness_state_topic': 'bedroom/rgb1/brightness/status', + 'brightness_command_topic': 'bedroom/rgb1/brightness/set', + 'optimistic': True + }, + { + 'platform': 'mqtt', + 'name': 'Kitchen light', + 'state_topic': 'kitchen/rgb1/light/status', + 'command_topic': 'kitchen/rgb1/light/switch', + 'brightness_state_topic': 'kitchen/rgb1/brightness/status', + 'brightness_command_topic': 'kitchen/rgb1/brightness/set', + 'optimistic': True + } + ] + }) + + start_hass_instance(cls.hass) + + # Kitchen light is explicitly excluded from being exposed + kitchen_light_entity = cls.hass.states.get('light.kitchen_light') + attrs = dict(kitchen_light_entity.attributes) + attrs[emulated_hue.ATTR_EMULATED_HUE] = False + cls.hass.states.set( + kitchen_light_entity.entity_id, kitchen_light_entity.state, + attributes=attrs) + + @classmethod + def tearDownClass(cls): + cls.hass.stop() + + def test_discover_lights(self): + result = requests.get( + BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('application/json' in result.headers['content-type']) + + result_json = result.json() + + # Make sure the lights we added to the config are there + self.assertTrue('light.office_light' in result_json) + self.assertTrue('light.bedroom_light' in result_json) + self.assertTrue('light.kitchen_light' not in result_json) + + def test_get_light_state(self): + # Turn office light on and set to 127 brightness + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_ON, + { + const.ATTR_ENTITY_ID: 'light.office_light', + light.ATTR_BRIGHTNESS: 127 + }, + blocking=True) + + office_json = self.perform_get_light_state('light.office_light', 200) + + self.assertEqual(office_json['state'][HUE_API_STATE_ON], True) + self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127) + + # Turn bedroom light off + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_OFF, + { + const.ATTR_ENTITY_ID: 'light.bedroom_light' + }, + blocking=True) + + bedroom_json = self.perform_get_light_state('light.bedroom_light', 200) + + self.assertEqual(bedroom_json['state'][HUE_API_STATE_ON], False) + self.assertEqual(bedroom_json['state'][HUE_API_STATE_BRI], 0) + + # Make sure kitchen light isn't accessible + kitchen_url = '/api/username/lights/{}'.format('light.kitchen_light') + kitchen_result = requests.get( + BRIDGE_URL_BASE.format(kitchen_url), timeout=5) + + self.assertEqual(kitchen_result.status_code, 404) + + def test_put_light_state(self): + self.perform_put_test_on_office_light() + + # Turn the bedroom light on first + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_ON, + {const.ATTR_ENTITY_ID: 'light.bedroom_light', + light.ATTR_BRIGHTNESS: 153}, + blocking=True) + + bedroom_light = self.hass.states.get('light.bedroom_light') + self.assertEqual(bedroom_light.state, STATE_ON) + self.assertEqual(bedroom_light.attributes[light.ATTR_BRIGHTNESS], 153) + + # Go through the API to turn it off + bedroom_result = self.perform_put_light_state( + 'light.bedroom_light', False) + + bedroom_result_json = bedroom_result.json() + + self.assertEqual(bedroom_result.status_code, 200) + self.assertTrue( + 'application/json' in bedroom_result.headers['content-type']) + + self.assertEqual(len(bedroom_result_json), 1) + + # Check to make sure the state changed + bedroom_light = self.hass.states.get('light.bedroom_light') + self.assertEqual(bedroom_light.state, STATE_OFF) + + # Make sure we can't change the kitchen light state + kitchen_result = self.perform_put_light_state( + 'light.kitchen_light', True) + self.assertEqual(kitchen_result.status_code, 404) + + def test_put_with_form_urlencoded_content_type(self): + # Needed for Alexa + self.perform_put_test_on_office_light( + 'application/x-www-form-urlencoded') + + # Make sure we fail gracefully when we can't parse the data + data = {'key1': 'value1', 'key2': 'value2'} + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("light.office_light")), + data=data) + + self.assertEqual(result.status_code, 400) + + def test_entity_not_found(self): + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format("not.existant_entity")), + timeout=5) + + self.assertEqual(result.status_code, 404) + + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("non.existant_entity")), + timeout=5) + + self.assertEqual(result.status_code, 404) + + def test_allowed_methods(self): + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("light.office_light"))) + + self.assertEqual(result.status_code, 405) + + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format("light.office_light")), + data={'key1': 'value1'}) + + self.assertEqual(result.status_code, 405) + + result = requests.put( + BRIDGE_URL_BASE.format('/api/username/lights'), + data={'key1': 'value1'}) + + self.assertEqual(result.status_code, 405) + + def test_proper_put_state_request(self): + # Test proper on value parsing + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("light.office_light")), + data=json.dumps({HUE_API_STATE_ON: 1234})) + + self.assertEqual(result.status_code, 400) + + # Test proper brightness value parsing + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("light.office_light")), + data=json.dumps({ + HUE_API_STATE_ON: True, + HUE_API_STATE_BRI: 'Hello world!' + })) + + self.assertEqual(result.status_code, 400) + + def perform_put_test_on_office_light(self, + content_type='application/json'): + # Turn the office light off first + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_OFF, + {const.ATTR_ENTITY_ID: 'light.office_light'}, + blocking=True) + + office_light = self.hass.states.get('light.office_light') + self.assertEqual(office_light.state, STATE_OFF) + + # Go through the API to turn it on + office_result = self.perform_put_light_state( + 'light.office_light', True, 56, content_type) + + office_result_json = office_result.json() + + self.assertEqual(office_result.status_code, 200) + self.assertTrue( + 'application/json' in office_result.headers['content-type']) + + self.assertEqual(len(office_result_json), 2) + + # Check to make sure the state changed + office_light = self.hass.states.get('light.office_light') + self.assertEqual(office_light.state, STATE_ON) + self.assertEqual(office_light.attributes[light.ATTR_BRIGHTNESS], 56) + + def perform_get_light_state(self, entity_id, expected_status): + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format(entity_id)), timeout=5) + + self.assertEqual(result.status_code, expected_status) + + if expected_status == 200: + self.assertTrue( + 'application/json' in result.headers['content-type']) + + return result.json() + + return None + + def perform_put_light_state(self, entity_id, is_on, brightness=None, + content_type='application/json'): + url = BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format(entity_id)) + + req_headers = {'Content-Type': content_type} + + data = {HUE_API_STATE_ON: is_on} + + if brightness is not None: + data[HUE_API_STATE_BRI] = brightness + + result = requests.put( + url, data=json.dumps(data), timeout=5, headers=req_headers) + return result + + +class MQTTBroker(object): + """Encapsulates an embedded MQTT broker.""" + + def __init__(self, host, port): + """Initialize a new instance.""" + from hbmqtt.broker import Broker + + self._loop = asyncio.new_event_loop() + + hbmqtt_config = { + 'listeners': { + 'default': { + 'max-connections': 50000, + 'type': 'tcp', + 'bind': '{}:{}'.format(host, port) + } + }, + 'auth': { + 'plugins': ['auth.anonymous'], + 'allow-anonymous': True + } + } + + self._broker = Broker(config=hbmqtt_config, loop=self._loop) + + self._thread = threading.Thread(target=self._run_loop) + self._started_ev = threading.Event() + + def start(self): + """Start the broker.""" + self._thread.start() + self._started_ev.wait() + + def stop(self): + """Stop the broker.""" + self._loop.call_soon_threadsafe(asyncio.async, self._broker.shutdown()) + self._loop.call_soon_threadsafe(self._loop.stop) + self._thread.join() + + def _run_loop(self): + asyncio.set_event_loop(self._loop) + self._loop.run_until_complete(self._broker_coroutine()) + + self._started_ev.set() + + self._loop.run_forever() + self._loop.close() + + @asyncio.coroutine + def _broker_coroutine(self): + yield from self._broker.start() From 2c26514c9536f1e9555d0efb8edf1d848814cb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Sandstr=C3=B6m?= Date: Sat, 27 Aug 2016 11:49:49 +0200 Subject: [PATCH 184/193] modbus sensor value scaling (#2972) --- homeassistant/components/sensor/modbus.py | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/sensor/modbus.py b/homeassistant/components/sensor/modbus.py index db024651b86..d6c85993162 100644 --- a/homeassistant/components/sensor/modbus.py +++ b/homeassistant/components/sensor/modbus.py @@ -26,11 +26,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if registers: for regnum, register in registers.items(): if register.get("name"): - sensors.append(ModbusSensor(register.get("name"), - slave, - regnum, - None, - register.get("unit"))) + sensors.append( + ModbusSensor(register.get("name"), + slave, + regnum, + None, + register.get("unit"), + scale=register.get("scale", 1), + offset=register.get("offset", 0), + precision=register.get("precision", 0))) if register.get("bits"): bits = register.get("bits") for bitnum, bit in bits.items(): @@ -53,8 +57,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ModbusSensor(Entity): """Representation of a Modbus Sensor.""" - # pylint: disable=too-many-arguments - def __init__(self, name, slave, register, bit=None, unit=None, coil=False): + # pylint: disable=too-many-arguments, too-many-instance-attributes + def __init__(self, name, slave, register, bit=None, unit=None, coil=False, + scale=1, offset=0, precision=0): """Initialize the sensor.""" self._name = name self.slave = int(slave) if slave else 1 @@ -63,6 +68,9 @@ class ModbusSensor(Entity): self._value = None self._unit = unit self._coil = coil + self._scale = scale + self._offset = offset + self._precision = precision def __str__(self): """Return the name and the state of the sensor.""" @@ -118,4 +126,6 @@ class ModbusSensor(Entity): if self.bit: self._value = val & (0x0001 << self.bit) else: - self._value = val + self._value = format( + self._scale * val + self._offset, + ".{}f".format(self._precision)) From f863efdaca6e4bd5986b4f92913e330980e7f2dc Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Sat, 27 Aug 2016 13:39:22 +0200 Subject: [PATCH 185/193] Use COMMAND_CLASS_THERMOSTAT_SETPOINT to get unit_of_measurement instad of COMMAND_CLASS_SENSOR_MULTILEVEL. Not all devices have multilevel sensor. (#3003) --- homeassistant/components/climate/zwave.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/climate/zwave.py b/homeassistant/components/climate/zwave.py index 54ca57e2163..24ef45eb952 100755 --- a/homeassistant/components/climate/zwave.py +++ b/homeassistant/components/climate/zwave.py @@ -110,6 +110,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): temps = [] for value in self._node.get_values( class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): + self._unit = value.units temps.append(int(value.data)) if value.index == self._index: self._target_temperature = int(value.data) @@ -128,7 +129,6 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): class_id=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(): From 6f1c97b9d3056acc81001485436b7770413d22db Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Sat, 27 Aug 2016 22:30:06 +0200 Subject: [PATCH 186/193] Voluptuous for AsusWRT (#2998) * Voluptuous for AsusWRT --- .../components/device_tracker/asuswrt.py | 46 +++++--- .../components/device_tracker/test_asuswrt.py | 108 ++++++++++++------ 2 files changed, 100 insertions(+), 54 deletions(-) diff --git a/homeassistant/components/device_tracker/asuswrt.py b/homeassistant/components/device_tracker/asuswrt.py index ec1d073c436..37e8cb0b2e7 100644 --- a/homeassistant/components/device_tracker/asuswrt.py +++ b/homeassistant/components/device_tracker/asuswrt.py @@ -12,14 +12,36 @@ import threading from collections import namedtuple from datetime import timedelta -from homeassistant.components.device_tracker import DOMAIN +import voluptuous as vol + +from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.helpers import validate_config from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) +CONF_PROTOCOL = 'protocol' +CONF_MODE = 'mode' +CONF_SSH_KEY = 'ssh_key' +CONF_PUB_KEY = 'pub_key' + +PLATFORM_SCHEMA = vol.All( + cv.has_at_least_one_key(CONF_PASSWORD, CONF_PUB_KEY, CONF_SSH_KEY), + PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_USERNAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_PROTOCOL, default='ssh'): + vol.Schema(['ssh', 'telnet']), + vol.Optional(CONF_MODE, default='router'): + vol.Schema(['router', 'ap']), + vol.Optional(CONF_SSH_KEY): cv.isfile, + vol.Optional(CONF_PUB_KEY): cv.isfile + })) + + _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['pexpect==4.0.1'] @@ -57,16 +79,6 @@ _IP_NEIGH_REGEX = re.compile( # pylint: disable=unused-argument def get_scanner(hass, config): """Validate the configuration and return an ASUS-WRT scanner.""" - if not validate_config(config, - {DOMAIN: [CONF_HOST, CONF_USERNAME]}, - _LOGGER): - return None - elif CONF_PASSWORD not in config[DOMAIN] and \ - 'ssh_key' not in config[DOMAIN] and \ - 'pub_key' not in config[DOMAIN]: - _LOGGER.error('Either a private key or password must be provided') - return None - scanner = AsusWrtDeviceScanner(config[DOMAIN]) return scanner if scanner.success_init else None @@ -83,11 +95,11 @@ class AsusWrtDeviceScanner(object): def __init__(self, config): """Initialize the scanner.""" self.host = config[CONF_HOST] - self.username = str(config[CONF_USERNAME]) - self.password = str(config.get(CONF_PASSWORD, '')) - self.ssh_key = str(config.get('ssh_key', config.get('pub_key', ''))) - self.protocol = config.get('protocol') - self.mode = config.get('mode') + self.username = config[CONF_USERNAME] + self.password = config.get(CONF_PASSWORD, '') + self.ssh_key = config.get('ssh_key', config.get('pub_key', '')) + self.protocol = config[CONF_PROTOCOL] + self.mode = config[CONF_MODE] self.lock = threading.Lock() diff --git a/tests/components/device_tracker/test_asuswrt.py b/tests/components/device_tracker/test_asuswrt.py index 241e4a65a0f..fc03426a7a1 100644 --- a/tests/components/device_tracker/test_asuswrt.py +++ b/tests/components/device_tracker/test_asuswrt.py @@ -1,34 +1,56 @@ """The tests for the ASUSWRT device tracker platform.""" - import os import unittest from unittest import mock +import voluptuous as vol + +from homeassistant.bootstrap import _setup_component from homeassistant.components import device_tracker +from homeassistant.components.device_tracker.asuswrt import ( + CONF_PROTOCOL, CONF_MODE, CONF_PUB_KEY, PLATFORM_SCHEMA, DOMAIN) from homeassistant.const import (CONF_PLATFORM, CONF_PASSWORD, CONF_USERNAME, CONF_HOST) -from tests.common import get_test_home_assistant +from tests.common import get_test_home_assistant, get_test_config_dir + +FAKEFILE = None + + +def setup_module(): + """Setup the test module.""" + global FAKEFILE + FAKEFILE = get_test_config_dir('fake_file') + with open(FAKEFILE, 'w') as out: + out.write(' ') + + +def teardown_module(): + """Tear down the module.""" + os.remove(FAKEFILE) class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): """Tests for the ASUSWRT device tracker platform.""" + hass = None - def setUp(self): # pylint: disable=invalid-name + def setup_method(self, _): """Setup things to be run when tests are started.""" self.hass = get_test_home_assistant() + self.hass.config.components = ['zone'] - def tearDown(self): # pylint: disable=invalid-name + def teardown_method(self, _): """Stop everything that was started.""" try: os.remove(self.hass.config.path(device_tracker.YAML_DEVICES)) except FileNotFoundError: pass - def test_password_or_pub_key_required(self): + def test_password_or_pub_key_required(self): \ + # pylint: disable=invalid-name """Test creating an AsusWRT scanner without a pass or pubkey.""" - self.assertIsNone(device_tracker.asuswrt.get_scanner( - self.hass, {device_tracker.DOMAIN: { + self.assertFalse(_setup_component( + self.hass, DOMAIN, {DOMAIN: { CONF_PLATFORM: 'asuswrt', CONF_HOST: 'fake_host', CONF_USERNAME: 'fake_user' @@ -37,36 +59,42 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): @mock.patch( 'homeassistant.components.device_tracker.asuswrt.AsusWrtDeviceScanner', return_value=mock.MagicMock()) - def test_get_scanner_with_password_no_pubkey(self, asuswrt_mock): + def test_get_scanner_with_password_no_pubkey(self, asuswrt_mock): \ + # pylint: disable=invalid-name """Test creating an AsusWRT scanner with a password and no pubkey.""" conf_dict = { - device_tracker.DOMAIN: { + DOMAIN: { CONF_PLATFORM: 'asuswrt', CONF_HOST: 'fake_host', CONF_USERNAME: 'fake_user', CONF_PASSWORD: 'fake_pass' } } - self.assertIsNotNone(device_tracker.asuswrt.get_scanner( - self.hass, conf_dict)) - asuswrt_mock.assert_called_once_with(conf_dict[device_tracker.DOMAIN]) + self.assertIsNotNone(_setup_component(self.hass, DOMAIN, conf_dict)) + conf_dict[DOMAIN][CONF_MODE] = 'router' + conf_dict[DOMAIN][CONF_PROTOCOL] = 'ssh' + asuswrt_mock.assert_called_once_with(conf_dict[DOMAIN]) @mock.patch( 'homeassistant.components.device_tracker.asuswrt.AsusWrtDeviceScanner', return_value=mock.MagicMock()) - def test_get_scanner_with_pubkey_no_password(self, asuswrt_mock): + def test_get_scanner_with_pubkey_no_password(self, asuswrt_mock): \ + # pylint: disable=invalid-name """Test creating an AsusWRT scanner with a pubkey and no password.""" conf_dict = { device_tracker.DOMAIN: { CONF_PLATFORM: 'asuswrt', CONF_HOST: 'fake_host', CONF_USERNAME: 'fake_user', - 'pub_key': '/fake_path' + CONF_PUB_KEY: FAKEFILE } } - self.assertIsNotNone(device_tracker.asuswrt.get_scanner( - self.hass, conf_dict)) - asuswrt_mock.assert_called_once_with(conf_dict[device_tracker.DOMAIN]) + + self.assertIsNotNone(_setup_component(self.hass, DOMAIN, conf_dict)) + + conf_dict[DOMAIN][CONF_MODE] = 'router' + conf_dict[DOMAIN][CONF_PROTOCOL] = 'ssh' + asuswrt_mock.assert_called_once_with(conf_dict[DOMAIN]) def test_ssh_login_with_pub_key(self): """Test that login is done with pub_key when configured to.""" @@ -74,12 +102,12 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh) ssh_mock.start() self.addCleanup(ssh_mock.stop) - conf_dict = { - CONF_PLATFORM: 'asuswrt', - CONF_HOST: 'fake_host', - CONF_USERNAME: 'fake_user', - 'pub_key': '/fake_path' - } + conf_dict = PLATFORM_SCHEMA({ + CONF_PLATFORM: 'asuswrt', + CONF_HOST: 'fake_host', + CONF_USERNAME: 'fake_user', + CONF_PUB_KEY: FAKEFILE + }) update_mock = mock.patch( 'homeassistant.components.device_tracker.asuswrt.' 'AsusWrtDeviceScanner.get_asuswrt_data') @@ -88,7 +116,7 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): asuswrt = device_tracker.asuswrt.AsusWrtDeviceScanner(conf_dict) asuswrt.ssh_connection() ssh.login.assert_called_once_with('fake_host', 'fake_user', - ssh_key='/fake_path') + ssh_key=FAKEFILE) def test_ssh_login_with_password(self): """Test that login is done with password when configured to.""" @@ -96,12 +124,12 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh) ssh_mock.start() self.addCleanup(ssh_mock.stop) - conf_dict = { - CONF_PLATFORM: 'asuswrt', - CONF_HOST: 'fake_host', - CONF_USERNAME: 'fake_user', - CONF_PASSWORD: 'fake_pass' - } + conf_dict = PLATFORM_SCHEMA({ + CONF_PLATFORM: 'asuswrt', + CONF_HOST: 'fake_host', + CONF_USERNAME: 'fake_user', + CONF_PASSWORD: 'fake_pass' + }) update_mock = mock.patch( 'homeassistant.components.device_tracker.asuswrt.' 'AsusWrtDeviceScanner.get_asuswrt_data') @@ -112,23 +140,29 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase): ssh.login.assert_called_once_with('fake_host', 'fake_user', 'fake_pass') - def test_ssh_login_without_password_or_pubkey(self): + def test_ssh_login_without_password_or_pubkey(self): \ + # pylint: disable=invalid-name """Test that login is not called without password or pub_key.""" ssh = mock.MagicMock() ssh_mock = mock.patch('pexpect.pxssh.pxssh', return_value=ssh) ssh_mock.start() self.addCleanup(ssh_mock.stop) + conf_dict = { - CONF_PLATFORM: 'asuswrt', - CONF_HOST: 'fake_host', - CONF_USERNAME: 'fake_user', + CONF_PLATFORM: 'asuswrt', + CONF_HOST: 'fake_host', + CONF_USERNAME: 'fake_user', } + + with self.assertRaises(vol.Invalid): + conf_dict = PLATFORM_SCHEMA(conf_dict) + update_mock = mock.patch( 'homeassistant.components.device_tracker.asuswrt.' 'AsusWrtDeviceScanner.get_asuswrt_data') update_mock.start() self.addCleanup(update_mock.stop) - asuswrt = device_tracker.asuswrt.AsusWrtDeviceScanner(conf_dict) - result = asuswrt.ssh_connection() + + self.assertFalse(_setup_component(self.hass, DOMAIN, + {DOMAIN: conf_dict})) ssh.login.assert_not_called() - self.assertIsNone(result) From 6acaf25b0d81468759c0ebb6a858de860ef21b2b Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Sat, 27 Aug 2016 22:41:21 +0200 Subject: [PATCH 187/193] Use voluptuous for mysensors (#2992) * Add voluptuous config validation for mysensors * Remove and clean up parts that are not needed for pymysensors 0.7. --- .../components/binary_sensor/mysensors.py | 4 +- homeassistant/components/light/mysensors.py | 5 +- homeassistant/components/mysensors.py | 108 ++++++++++-------- homeassistant/components/sensor/mysensors.py | 6 +- homeassistant/components/switch/mysensors.py | 2 +- 5 files changed, 68 insertions(+), 57 deletions(-) diff --git a/homeassistant/components/binary_sensor/mysensors.py b/homeassistant/components/binary_sensor/mysensors.py index d7b1a82188e..789e188537e 100644 --- a/homeassistant/components/binary_sensor/mysensors.py +++ b/homeassistant/components/binary_sensor/mysensors.py @@ -32,7 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): pres.S_MOTION: [set_req.V_TRIPPED], pres.S_SMOKE: [set_req.V_TRIPPED], } - if float(gateway.version) >= 1.5: + if float(gateway.protocol_version) >= 1.5: map_sv_types.update({ pres.S_SPRINKLER: [set_req.V_TRIPPED], pres.S_WATER_LEAK: [set_req.V_TRIPPED], @@ -66,7 +66,7 @@ class MySensorsBinarySensor( pres.S_MOTION: 'motion', pres.S_SMOKE: 'smoke', } - if float(self.gateway.version) >= 1.5: + if float(self.gateway.protocol_version) >= 1.5: class_map.update({ pres.S_SPRINKLER: 'sprinkler', pres.S_WATER_LEAK: 'leak', diff --git a/homeassistant/components/light/mysensors.py b/homeassistant/components/light/mysensors.py index 434eb4f2f22..c33793127a2 100644 --- a/homeassistant/components/light/mysensors.py +++ b/homeassistant/components/light/mysensors.py @@ -40,7 +40,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): device_class_map = { pres.S_DIMMER: MySensorsLightDimmer, } - if float(gateway.version) >= 1.5: + if float(gateway.protocol_version) >= 1.5: # Add V_RGBW when rgb_white is implemented in the frontend map_sv_types.update({ pres.S_RGB_LIGHT: [set_req.V_RGB], @@ -169,7 +169,7 @@ class MySensorsLight(mysensors.MySensorsDeviceEntity, Light): def _turn_off_rgb_or_w(self, value_type=None, value=None): """Turn off RGB or RGBW child device.""" - if float(self.gateway.version) >= 1.5: + if float(self.gateway.protocol_version) >= 1.5: set_req = self.gateway.const.SetReq if self.value_type == set_req.V_RGB: value = '000000' @@ -227,7 +227,6 @@ class MySensorsLight(mysensors.MySensorsDeviceEntity, Light): """Update the controller with the latest value from a sensor.""" node = self.gateway.sensors[self.node_id] child = node.children[self.child_id] - self.battery_level = node.battery_level for value_type, value in child.values.items(): _LOGGER.debug( '%s: value_type %s, value = %s', self._name, value_type, value) diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index 5169e86ff04..4b9b54d61db 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -7,59 +7,74 @@ https://home-assistant.io/components/sensor.mysensors/ import logging import socket +import voluptuous as vol + from homeassistant.bootstrap import setup_component +import homeassistant.helpers.config_validation as cv from homeassistant.const import (ATTR_BATTERY_LEVEL, CONF_OPTIMISTIC, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, STATE_OFF, STATE_ON) -from homeassistant.helpers import discovery, validate_config +from homeassistant.helpers import discovery from homeassistant.loader import get_component -CONF_GATEWAYS = 'gateways' +_LOGGER = logging.getLogger(__name__) + +ATTR_NODE_ID = 'node_id' +ATTR_CHILD_ID = 'child_id' +ATTR_DESCRIPTION = 'description' +ATTR_DEVICE = 'device' +CONF_BAUD_RATE = 'baud_rate' CONF_DEVICE = 'device' CONF_DEBUG = 'debug' +CONF_GATEWAYS = 'gateways' CONF_PERSISTENCE = 'persistence' CONF_PERSISTENCE_FILE = 'persistence_file' -CONF_VERSION = 'version' -CONF_BAUD_RATE = 'baud_rate' CONF_TCP_PORT = 'tcp_port' CONF_TOPIC_IN_PREFIX = 'topic_in_prefix' CONF_TOPIC_OUT_PREFIX = 'topic_out_prefix' CONF_RETAIN = 'retain' -DEFAULT_VERSION = '1.4' +CONF_VERSION = 'version' +DEFAULT_VERSION = 1.4 DEFAULT_BAUD_RATE = 115200 DEFAULT_TCP_PORT = 5003 - DOMAIN = 'mysensors' -DEPENDENCIES = [] +GATEWAYS = None MQTT_COMPONENT = 'mqtt' REQUIREMENTS = [ 'https://github.com/theolind/pymysensors/archive/' '8ce98b7fb56f7921a808eb66845ce8b2c455c81e.zip#pymysensors==0.7.1'] -_LOGGER = logging.getLogger(__name__) -ATTR_NODE_ID = 'node_id' -ATTR_CHILD_ID = 'child_id' -ATTR_DEVICE = 'device' -GATEWAYS = None +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_GATEWAYS): vol.All(cv.ensure_list, [ + { + vol.Required(CONF_DEVICE): cv.string, + vol.Optional(CONF_PERSISTENCE_FILE): cv.string, + vol.Optional( + CONF_BAUD_RATE, + default=DEFAULT_BAUD_RATE): cv.positive_int, + vol.Optional( + CONF_TCP_PORT, + default=DEFAULT_TCP_PORT): cv.port, + vol.Optional(CONF_TOPIC_IN_PREFIX, default=''): cv.string, + vol.Optional(CONF_TOPIC_OUT_PREFIX, default=''): cv.string, + }, + ]), + vol.Optional(CONF_DEBUG, default=False): cv.boolean, + vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, + vol.Optional(CONF_PERSISTENCE, default=True): cv.boolean, + vol.Optional(CONF_RETAIN, default=True): cv.boolean, + vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): vol.Coerce(float), + }) +}, extra=vol.ALLOW_EXTRA) def setup(hass, config): # pylint: disable=too-many-locals """Setup the MySensors component.""" - if not validate_config(config, - {DOMAIN: [CONF_GATEWAYS]}, - _LOGGER): - return False - if not all(CONF_DEVICE in gateway - for gateway in config[DOMAIN][CONF_GATEWAYS]): - _LOGGER.error('Missing required configuration items ' - 'in %s: %s', DOMAIN, CONF_DEVICE) - return False - import mysensors.mysensors as mysensors - version = str(config[DOMAIN].get(CONF_VERSION, DEFAULT_VERSION)) - is_metric = hass.config.units.is_metric - persistence = config[DOMAIN].get(CONF_PERSISTENCE, True) + version = config[DOMAIN].get(CONF_VERSION) + persistence = config[DOMAIN].get(CONF_PERSISTENCE) def setup_gateway(device, persistence_file, baud_rate, tcp_port, in_prefix, out_prefix): @@ -69,7 +84,7 @@ def setup(hass, config): # pylint: disable=too-many-locals if not setup_component(hass, MQTT_COMPONENT, config): return mqtt = get_component(MQTT_COMPONENT) - retain = config[DOMAIN].get(CONF_RETAIN, True) + retain = config[DOMAIN].get(CONF_RETAIN) def pub_callback(topic, payload, qos, retain): """Call mqtt publish function.""" @@ -98,10 +113,10 @@ def setup(hass, config): # pylint: disable=too-many-locals device, event_callback=None, persistence=persistence, persistence_file=persistence_file, protocol_version=version, baud=baud_rate) - gateway.metric = is_metric - gateway.debug = config[DOMAIN].get(CONF_DEBUG, False) - optimistic = config[DOMAIN].get(CONF_OPTIMISTIC, False) - gateway = GatewayWrapper(gateway, version, optimistic, device) + gateway.metric = hass.config.units.is_metric + gateway.debug = config[DOMAIN].get(CONF_DEBUG) + optimistic = config[DOMAIN].get(CONF_OPTIMISTIC) + gateway = GatewayWrapper(gateway, optimistic, device) # pylint: disable=attribute-defined-outside-init gateway.event_callback = gateway.callback_factory() @@ -122,18 +137,16 @@ def setup(hass, config): # pylint: disable=too-many-locals global GATEWAYS GATEWAYS = {} conf_gateways = config[DOMAIN][CONF_GATEWAYS] - if isinstance(conf_gateways, dict): - conf_gateways = [conf_gateways] for index, gway in enumerate(conf_gateways): device = gway[CONF_DEVICE] persistence_file = gway.get( CONF_PERSISTENCE_FILE, hass.config.path('mysensors{}.pickle'.format(index + 1))) - baud_rate = gway.get(CONF_BAUD_RATE, DEFAULT_BAUD_RATE) - tcp_port = gway.get(CONF_TCP_PORT, DEFAULT_TCP_PORT) - in_prefix = gway.get(CONF_TOPIC_IN_PREFIX, '') - out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX, '') + baud_rate = gway.get(CONF_BAUD_RATE) + tcp_port = gway.get(CONF_TCP_PORT) + in_prefix = gway.get(CONF_TOPIC_IN_PREFIX) + out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX) GATEWAYS[device] = setup_gateway( device, persistence_file, baud_rate, tcp_port, in_prefix, out_prefix) @@ -189,24 +202,22 @@ class GatewayWrapper(object): # pylint: disable=too-few-public-methods - def __init__(self, gateway, version, optimistic, device): + def __init__(self, gateway, optimistic, device): """Setup class attributes on instantiation. Args: - gateway (mysensors.Gateway): Gateway to wrap. - version (str): Version of mysensors API. + gateway (mysensors.SerialGateway): Gateway to wrap. optimistic (bool): Send values to actuators without feedback state. device (str): Path to serial port, ip adress or mqtt. Attributes: - _wrapped_gateway (mysensors.Gateway): Wrapped gateway. - version (str): Version of mysensors API. + _wrapped_gateway (mysensors.SerialGateway): Wrapped gateway. platform_callbacks (list): Callback functions, one per platform. optimistic (bool): Send values to actuators without feedback state. + device (str): Device configured as gateway. __initialised (bool): True if GatewayWrapper is initialised. """ self._wrapped_gateway = gateway - self.version = version self.platform_callbacks = [] self.optimistic = optimistic self.device = device @@ -244,7 +255,7 @@ class GatewayWrapper(object): class MySensorsDeviceEntity(object): """Represent a MySensors entity.""" - # pylint: disable=too-many-arguments,too-many-instance-attributes + # pylint: disable=too-many-arguments def __init__( self, gateway, node_id, child_id, name, value_type, child_type): @@ -276,7 +287,6 @@ class MySensorsDeviceEntity(object): self._name = name self.value_type = value_type self.child_type = child_type - self.battery_level = 0 self._values = {} @property @@ -292,11 +302,14 @@ class MySensorsDeviceEntity(object): @property def device_state_attributes(self): """Return device specific state attributes.""" + node = self.gateway.sensors[self.node_id] + child = node.children[self.child_id] attr = { + ATTR_BATTERY_LEVEL: node.battery_level, + ATTR_CHILD_ID: self.child_id, + ATTR_DESCRIPTION: child.description, ATTR_DEVICE: self.gateway.device, ATTR_NODE_ID: self.node_id, - ATTR_CHILD_ID: self.child_id, - ATTR_BATTERY_LEVEL: self.battery_level, } set_req = self.gateway.const.SetReq @@ -307,7 +320,7 @@ class MySensorsDeviceEntity(object): except ValueError: _LOGGER.error('Value_type %s is not valid for mysensors ' 'version %s', value_type, - self.gateway.version) + self.gateway.protocol_version) return attr @property @@ -319,7 +332,6 @@ class MySensorsDeviceEntity(object): """Update the controller with the latest value from a sensor.""" node = self.gateway.sensors[self.node_id] child = node.children[self.child_id] - self.battery_level = node.battery_level set_req = self.gateway.const.SetReq for value_type, value in child.values.items(): _LOGGER.debug( diff --git a/homeassistant/components/sensor/mysensors.py b/homeassistant/components/sensor/mysensors.py index b58a375755c..eff67a1f9e2 100644 --- a/homeassistant/components/sensor/mysensors.py +++ b/homeassistant/components/sensor/mysensors.py @@ -47,12 +47,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): pres.S_SCENE_CONTROLLER: [set_req.V_SCENE_ON, set_req.V_SCENE_OFF], } - if float(gateway.version) < 1.5: + if float(gateway.protocol_version) < 1.5: map_sv_types.update({ pres.S_AIR_QUALITY: [set_req.V_DUST_LEVEL], pres.S_DUST: [set_req.V_DUST_LEVEL], }) - if float(gateway.version) >= 1.5: + if float(gateway.protocol_version) >= 1.5: map_sv_types.update({ pres.S_COLOR_SENSOR: [set_req.V_RGB], pres.S_MULTIMETER: [set_req.V_VOLTAGE, @@ -99,7 +99,7 @@ class MySensorsSensor(mysensors.MySensorsDeviceEntity, Entity): set_req.V_VOLTAGE: 'V', set_req.V_CURRENT: 'A', } - if float(self.gateway.version) >= 1.5: + if float(self.gateway.protocol_version) >= 1.5: if set_req.V_UNIT_PREFIX in self._values: return self._values[ set_req.V_UNIT_PREFIX] diff --git a/homeassistant/components/switch/mysensors.py b/homeassistant/components/switch/mysensors.py index 102490286f6..6e0ed7528a2 100644 --- a/homeassistant/components/switch/mysensors.py +++ b/homeassistant/components/switch/mysensors.py @@ -55,7 +55,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): pres.S_LOCK: MySensorsSwitch, pres.S_IR: MySensorsIRSwitch, } - if float(gateway.version) >= 1.5: + if float(gateway.protocol_version) >= 1.5: map_sv_types.update({ pres.S_BINARY: [set_req.V_STATUS, set_req.V_LIGHT], pres.S_SPRINKLER: [set_req.V_STATUS], From e6b9d5f5b35aae3b48a8b798a1d7e5eee965936a Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 27 Aug 2016 22:42:34 +0200 Subject: [PATCH 188/193] Migrate to voluptuous (#2989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🍪 🐬 --- homeassistant/components/camera/generic.py | 32 +++++++-------- homeassistant/components/camera/mjpeg.py | 46 +++++++++++++--------- homeassistant/const.py | 4 ++ 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/camera/generic.py b/homeassistant/components/camera/generic.py index a03acc32eb8..85a662065a6 100644 --- a/homeassistant/components/camera/generic.py +++ b/homeassistant/components/camera/generic.py @@ -10,37 +10,35 @@ import requests from requests.auth import HTTPBasicAuth, HTTPDigestAuth import voluptuous as vol -from homeassistant.const import CONF_NAME, CONF_USERNAME, CONF_PASSWORD +from homeassistant.const import ( + CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_AUTHENTICATION, + HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION) from homeassistant.exceptions import TemplateError -from homeassistant.components.camera import PLATFORM_SCHEMA, Camera +from homeassistant.components.camera import (PLATFORM_SCHEMA, Camera) from homeassistant.helpers import config_validation as cv, template - _LOGGER = logging.getLogger(__name__) -CONF_AUTHENTICATION = 'authentication' -CONF_STILL_IMAGE_URL = 'still_image_url' CONF_LIMIT_REFETCH_TO_URL_CHANGE = 'limit_refetch_to_url_change' +CONF_STILL_IMAGE_URL = 'still_image_url' + DEFAULT_NAME = 'Generic Camera' -BASIC_AUTHENTICATION = 'basic' -DIGEST_AUTHENTICATION = 'digest' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - # pylint: disable=no-value-for-parameter - vol.Required(CONF_STILL_IMAGE_URL): vol.Any(vol.Url(), cv.template), - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_USERNAME): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, - vol.Optional(CONF_AUTHENTICATION, default=BASIC_AUTHENTICATION): - vol.In([BASIC_AUTHENTICATION, DIGEST_AUTHENTICATION]), + vol.Required(CONF_STILL_IMAGE_URL): vol.Any(cv.url, cv.template), + vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION): + vol.In([HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]), vol.Optional(CONF_LIMIT_REFETCH_TO_URL_CHANGE, default=False): cv.boolean, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_USERNAME): cv.string, }) # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup a generic IP Camera.""" - add_devices_callback([GenericCamera(config)]) + add_devices([GenericCamera(config)]) # pylint: disable=too-many-instance-attributes @@ -58,7 +56,7 @@ class GenericCamera(Camera): password = device_info.get(CONF_PASSWORD) if username and password: - if device_info[CONF_AUTHENTICATION] == DIGEST_AUTHENTICATION: + if device_info[CONF_AUTHENTICATION] == HTTP_DIGEST_AUTHENTICATION: self._auth = HTTPDigestAuth(username, password) else: self._auth = HTTPBasicAuth(username, password) diff --git a/homeassistant/components/camera/mjpeg.py b/homeassistant/components/camera/mjpeg.py index 16897df315b..04f099d8b1e 100644 --- a/homeassistant/components/camera/mjpeg.py +++ b/homeassistant/components/camera/mjpeg.py @@ -9,26 +9,35 @@ from contextlib import closing import requests from requests.auth import HTTPBasicAuth, HTTPDigestAuth +import voluptuous as vol -from homeassistant.components.camera import DOMAIN, Camera -from homeassistant.helpers import validate_config - -CONTENT_TYPE_HEADER = 'Content-Type' +from homeassistant.const import ( + CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_AUTHENTICATION, + HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION) +from homeassistant.components.camera import (PLATFORM_SCHEMA, Camera) +from homeassistant.helpers import config_validation as cv _LOGGER = logging.getLogger(__name__) -BASIC_AUTHENTICATION = 'basic' -DIGEST_AUTHENTICATION = 'digest' +CONF_MJPEG_URL = 'mjpeg_url' +CONTENT_TYPE_HEADER = 'Content-Type' + +DEFAULT_NAME = 'Mjpeg Camera' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_MJPEG_URL): cv.url, + vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION): + vol.In([HTTP_BASIC_AUTHENTICATION, HTTP_DIGEST_AUTHENTICATION]), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PASSWORD): cv.string, + vol.Optional(CONF_USERNAME): cv.string, +}) # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup a MJPEG IP Camera.""" - if not validate_config({DOMAIN: config}, {DOMAIN: ['mjpeg_url']}, - _LOGGER): - return None - - add_devices_callback([MjpegCamera(config)]) + add_devices([MjpegCamera(config)]) def extract_image_from_mjpeg(stream): @@ -50,17 +59,16 @@ class MjpegCamera(Camera): def __init__(self, device_info): """Initialize a MJPEG camera.""" super().__init__() - self._name = device_info.get('name', 'Mjpeg Camera') - self._authentication = device_info.get('authentication', - BASIC_AUTHENTICATION) - self._username = device_info.get('username') - self._password = device_info.get('password') - self._mjpeg_url = device_info['mjpeg_url'] + self._name = device_info.get(CONF_NAME) + self._authentication = device_info.get(CONF_AUTHENTICATION) + self._username = device_info.get(CONF_USERNAME) + self._password = device_info.get(CONF_PASSWORD) + self._mjpeg_url = device_info[CONF_MJPEG_URL] def camera_stream(self): """Return a MJPEG stream image response directly from the camera.""" if self._username and self._password: - if self._authentication == DIGEST_AUTHENTICATION: + if self._authentication == HTTP_DIGEST_AUTHENTICATION: auth = HTTPDigestAuth(self._username, self._password) else: auth = HTTPBasicAuth(self._username, self._password) diff --git a/homeassistant/const.py b/homeassistant/const.py index b296a4959b1..76fc1226ca1 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -23,6 +23,7 @@ CONF_ACCESS_TOKEN = 'access_token' CONF_AFTER = 'after' CONF_ALIAS = 'alias' CONF_API_KEY = 'api_key' +CONF_AUTHENTICATION = 'authentication' CONF_BEFORE = 'before' CONF_BELOW = 'below' CONF_BLACKLIST = 'blacklist' @@ -280,6 +281,9 @@ HTTP_METHOD_NOT_ALLOWED = 405 HTTP_UNPROCESSABLE_ENTITY = 422 HTTP_INTERNAL_SERVER_ERROR = 500 +HTTP_BASIC_AUTHENTICATION = 'basic' +HTTP_DIGEST_AUTHENTICATION = 'digest' + HTTP_HEADER_HA_AUTH = 'X-HA-access' HTTP_HEADER_ACCEPT_ENCODING = 'Accept-Encoding' HTTP_HEADER_CONTENT_TYPE = 'Content-type' From 2accc15d413edda1ecf94b86d66cef197b855ee6 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 27 Aug 2016 22:43:33 +0200 Subject: [PATCH 189/193] Migrate to voluptuous (#2991) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐬 --- homeassistant/components/camera/ffmpeg.py | 24 +++++++------- homeassistant/components/camera/foscam.py | 40 +++++++++++++++-------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/camera/ffmpeg.py b/homeassistant/components/camera/ffmpeg.py index 1eaabc45195..f87b3074c1c 100644 --- a/homeassistant/components/camera/ffmpeg.py +++ b/homeassistant/components/camera/ffmpeg.py @@ -9,31 +9,33 @@ from contextlib import closing import voluptuous as vol -from homeassistant.components.camera import Camera +from homeassistant.components.camera import (Camera, PLATFORM_SCHEMA) from homeassistant.components.camera.mjpeg import extract_image_from_mjpeg import homeassistant.helpers.config_validation as cv -from homeassistant.const import CONF_NAME, CONF_PLATFORM +from homeassistant.const import CONF_NAME -REQUIREMENTS = ["ha-ffmpeg==0.8"] +REQUIREMENTS = ['ha-ffmpeg==0.8'] + +_LOGGER = logging.getLogger(__name__) CONF_INPUT = 'input' CONF_FFMPEG_BIN = 'ffmpeg_bin' CONF_EXTRA_ARGUMENTS = 'extra_arguments' -PLATFORM_SCHEMA = vol.Schema({ - vol.Required(CONF_PLATFORM): "ffmpeg", - vol.Optional(CONF_NAME, default="FFmpeg"): cv.string, +DEFAULT_BINARY = 'ffmpeg' +DEFAULT_NAME = 'FFmpeg' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_INPUT): cv.string, - vol.Optional(CONF_FFMPEG_BIN, default="ffmpeg"): cv.string, vol.Optional(CONF_EXTRA_ARGUMENTS): cv.string, + vol.Optional(CONF_FFMPEG_BIN, default=DEFAULT_BINARY): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) -_LOGGER = logging.getLogger(__name__) - -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup a FFmpeg Camera.""" - add_devices_callback([FFmpegCamera(config)]) + add_devices([FFmpegCamera(config)]) class FFmpegCamera(Camera): diff --git a/homeassistant/components/camera/foscam.py b/homeassistant/components/camera/foscam.py index 95a6460b814..987b8c51af5 100644 --- a/homeassistant/components/camera/foscam.py +++ b/homeassistant/components/camera/foscam.py @@ -7,21 +7,33 @@ https://home-assistant.io/components/camera.foscam/ import logging import requests +import voluptuous as vol -from homeassistant.components.camera import DOMAIN, Camera -from homeassistant.helpers import validate_config +from homeassistant.components.camera import (Camera, PLATFORM_SCHEMA) +from homeassistant.const import ( + CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_PORT) +from homeassistant.helpers import config_validation as cv _LOGGER = logging.getLogger(__name__) +CONF_IP = 'ip' + +DEFAULT_NAME = 'Foscam Camera' +DEFAULT_PORT = 88 + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_IP): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Required(CONF_USERNAME): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, +}) + # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup a Foscam IP Camera.""" - if not validate_config({DOMAIN: config}, - {DOMAIN: ['username', 'password', 'ip']}, _LOGGER): - return None - - add_devices_callback([FoscamCamera(config)]) + add_devices([FoscamCamera(config)]) # pylint: disable=too-many-instance-attributes @@ -32,16 +44,16 @@ class FoscamCamera(Camera): """Initialize a Foscam camera.""" super(FoscamCamera, self).__init__() - ip_address = device_info.get('ip') - port = device_info.get('port', 88) + ip_address = device_info.get(CONF_IP) + port = device_info.get(CONF_PORT) - self._base_url = 'http://' + ip_address + ':' + str(port) + '/' - self._username = device_info.get('username') - self._password = device_info.get('password') + self._base_url = 'http://{}:{}/'.format(ip_address, port) + self._username = device_info.get(CONF_USERNAME) + self._password = device_info.get(CONF_PASSWORD) self._snap_picture_url = self._base_url \ + 'cgi-bin/CGIProxy.fcgi?cmd=snapPicture2&usr=' \ + self._username + '&pwd=' + self._password - self._name = device_info.get('name', 'Foscam Camera') + self._name = device_info.get(CONF_NAME) _LOGGER.info('Using the following URL for %s: %s', self._name, self._snap_picture_url) From a4b90c987990e8a3ce8bcce163ed1af7b5b2db9c Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 27 Aug 2016 22:44:22 +0200 Subject: [PATCH 190/193] Use voluptuous for Raspberry Pi and local file camera (#2988) * Migrate to voluptuous * Update const.py * Migrate to voluptuous * Remove duplicate _LOGGER entry --- homeassistant/components/camera/local_file.py | 11 ++- homeassistant/components/camera/rpi_camera.py | 96 +++++++++++++------ homeassistant/const.py | 1 + 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/camera/local_file.py b/homeassistant/components/camera/local_file.py index f7df934d9de..65defb4557b 100644 --- a/homeassistant/components/camera/local_file.py +++ b/homeassistant/components/camera/local_file.py @@ -1,5 +1,9 @@ -"""Camera that loads a picture from a local file.""" +""" +Camera that loads a picture from a local file. +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/camera.local_file/ +""" import logging import os @@ -9,7 +13,10 @@ from homeassistant.const import CONF_NAME from homeassistant.components.camera import Camera, PLATFORM_SCHEMA from homeassistant.helpers import config_validation as cv +_LOGGER = logging.getLogger(__name__) + CONF_FILE_PATH = 'file_path' + DEFAULT_NAME = 'Local File' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -17,8 +24,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string }) -_LOGGER = logging.getLogger(__name__) - def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Camera.""" diff --git a/homeassistant/components/camera/rpi_camera.py b/homeassistant/components/camera/rpi_camera.py index ee67d097286..22ab72ad8e7 100644 --- a/homeassistant/components/camera/rpi_camera.py +++ b/homeassistant/components/camera/rpi_camera.py @@ -9,41 +9,77 @@ import subprocess import logging import shutil -from homeassistant.components.camera import Camera +import voluptuous as vol + +from homeassistant.components.camera import (Camera, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_NAME, CONF_FILE_PATH) +from homeassistant.helpers import config_validation as cv _LOGGER = logging.getLogger(__name__) +CONF_HORIZONTAL_FLIP = 'horizontal_flip' +CONF_IMAGE_HEIGHT = 'image_height' +CONF_IMAGE_QUALITY = 'image_quality' +CONF_IMAGE_ROTATION = 'image_rotation' +CONF_IMAGE_WIDTH = 'image_width' +CONF_TIMELAPSE = 'timelapse' +CONF_VERTICAL_FLIP = 'vertical_flip' + +DEFAULT_HORIZONTAL_FLIP = 0 +DEFAULT_IMAGE_HEIGHT = 480 +DEFAULT_IMAGE_QUALITIY = 7 +DEFAULT_IMAGE_ROTATION = 0 +DEFAULT_IMAGE_WIDTH = 640 +DEFAULT_NAME = 'Raspberry Pi Camera' +DEFAULT_TIMELAPSE = 1000 +DEFAULT_VERTICAL_FLIP = 0 + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_FILE_PATH): cv.isfile, + vol.Optional(CONF_HORIZONTAL_FLIP, default=DEFAULT_HORIZONTAL_FLIP): + vol.All(vol.Coerce(int), vol.Range(min=0, max=1)), + vol.Optional(CONF_IMAGE_HEIGHT, default=DEFAULT_HORIZONTAL_FLIP): + vol.Coerce(int), + vol.Optional(CONF_IMAGE_QUALITY, default=DEFAULT_IMAGE_QUALITIY): + vol.All(vol.Coerce(int), vol.Range(min=0, max=100)), + vol.Optional(CONF_IMAGE_ROTATION, default=DEFAULT_IMAGE_ROTATION): + vol.All(vol.Coerce(int), vol.Range(min=0, max=359)), + vol.Optional(CONF_IMAGE_WIDTH, default=DEFAULT_IMAGE_WIDTH): + vol.Coerce(int), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_TIMELAPSE, default=1000): vol.Coerce(int), + vol.Optional(CONF_VERTICAL_FLIP, default=DEFAULT_VERTICAL_FLIP): + vol.All(vol.Coerce(int), vol.Range(min=0, max=1)), +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Raspberry Camera.""" if shutil.which("raspistill") is None: - _LOGGER.error("Error: raspistill not found") + _LOGGER.error("'raspistill' was not found") return False setup_config = ( { - "name": config.get("name", "Raspberry Pi Camera"), - "image_width": int(config.get("image_width", "640")), - "image_height": int(config.get("image_height", "480")), - "image_quality": int(config.get("image_quality", "7")), - "image_rotation": int(config.get("image_rotation", "0")), - "timelapse": int(config.get("timelapse", "2000")), - "horizontal_flip": int(config.get("horizontal_flip", "0")), - "vertical_flip": int(config.get("vertical_flip", "0")), - "file_path": config.get("file_path", - os.path.join(os.path.dirname(__file__), - 'image.jpg')) + CONF_NAME: config.get(CONF_NAME), + CONF_IMAGE_WIDTH: config.get(CONF_IMAGE_WIDTH), + CONF_IMAGE_HEIGHT: config.get(CONF_IMAGE_HEIGHT), + CONF_IMAGE_QUALITY: config.get(CONF_IMAGE_QUALITY), + CONF_IMAGE_ROTATION: config.get(CONF_IMAGE_ROTATION), + CONF_TIMELAPSE: config.get(CONF_TIMELAPSE), + CONF_HORIZONTAL_FLIP: config.get(CONF_HORIZONTAL_FLIP), + CONF_VERTICAL_FLIP: config.get(CONF_VERTICAL_FLIP), + CONF_FILE_PATH: config.get(CONF_FILE_PATH, + os.path.join(os.path.dirname(__file__), + 'image.jpg')) } ) - # check filepath given is writable - if not os.access(setup_config["file_path"], os.W_OK): - _LOGGER.error("Error: file path is not writable") + if not os.access(setup_config[CONF_FILE_PATH], os.W_OK): + _LOGGER.error("File path is not writable") return False - add_devices([ - RaspberryCamera(setup_config) - ]) + add_devices([RaspberryCamera(setup_config)]) class RaspberryCamera(Camera): @@ -53,26 +89,26 @@ class RaspberryCamera(Camera): """Initialize Raspberry Pi camera component.""" super().__init__() - self._name = device_info["name"] + self._name = device_info[CONF_NAME] self._config = device_info - # kill if there's raspistill instance + # Kill if there's raspistill instance subprocess.Popen(['killall', 'raspistill'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT) cmd_args = [ - 'raspistill', '--nopreview', '-o', str(device_info["file_path"]), - '-t', '0', '-w', str(device_info["image_width"]), - '-h', str(device_info["image_height"]), - '-tl', str(device_info["timelapse"]), - '-q', str(device_info["image_quality"]), - '-rot', str(device_info["image_rotation"]) + 'raspistill', '--nopreview', '-o', device_info[CONF_FILE_PATH], + '-t', '0', '-w', str(device_info[CONF_IMAGE_WIDTH]), + '-h', str(device_info[CONF_IMAGE_HEIGHT]), + '-tl', str(device_info[CONF_TIMELAPSE]), + '-q', str(device_info[CONF_IMAGE_QUALITY]), + '-rot', str(device_info[CONF_IMAGE_ROTATION]) ] - if device_info["horizontal_flip"]: + if device_info[CONF_HORIZONTAL_FLIP]: cmd_args.append("-hf") - if device_info["vertical_flip"]: + if device_info[CONF_VERTICAL_FLIP]: cmd_args.append("-vf") subprocess.Popen(cmd_args, @@ -81,7 +117,7 @@ class RaspberryCamera(Camera): def camera_image(self): """Return raspstill image response.""" - with open(self._config["file_path"], 'rb') as file: + with open(self._config[CONF_FILE_PATH], 'rb') as file: return file.read() @property diff --git a/homeassistant/const.py b/homeassistant/const.py index 76fc1226ca1..dc6f7f18345 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -37,6 +37,7 @@ CONF_ELEVATION = 'elevation' CONF_ENTITY_ID = 'entity_id' CONF_ENTITY_NAMESPACE = 'entity_namespace' CONF_EVENT = 'event' +CONF_FILE_PATH = 'file_path' CONF_FILENAME = 'filename' CONF_HOST = 'host' CONF_HOSTS = 'hosts' From fdb6de4d2332f05d6797068c2da797f9fcc87abf Mon Sep 17 00:00:00 2001 From: Teagan Glenn Date: Sat, 27 Aug 2016 14:53:12 -0600 Subject: [PATCH 191/193] Fan demo (#2976) * Update attr to property and default state method * State prop is defined in parent class * Demo platform fan * PyDoc * Copy-pasta artifact * PyDoc * Linting * Raise error if turn_off and turn_on not implemented * Update demo platform * Initial unit test commit * Readability * Unneeded typing * Should inherit from fan entity * Turn off polling * Initial oscillating flag * Pass HASS into demo * Typing * Invoke set_speed instead of setting directly * Service update * Update demo tests * Forgot to block after service call. * linting * Test to make sure not implemented is thrown * Is On Method test * Update const to match string * Update services yaml * Toggle method * Toggle service * Typing * TYPE O * Attribute check * Type-o * Type-o * Put typing back * ToggleEntity * Linting * Linting * Oops * Stale prints * Demo support --- homeassistant/components/fan/__init__.py | 61 ++++++++++----- homeassistant/components/fan/demo.py | 75 ++++++++++++++++++ homeassistant/components/fan/insteon_hub.py | 5 -- homeassistant/components/fan/services.yaml | 12 ++- tests/components/fan/__init__.py | 38 ++++++++++ tests/components/fan/test_demo.py | 84 +++++++++++++++++++++ tests/components/fan/test_insteon_hub.py | 25 +++--- 7 files changed, 260 insertions(+), 40 deletions(-) create mode 100644 homeassistant/components/fan/demo.py create mode 100644 tests/components/fan/test_demo.py diff --git a/homeassistant/components/fan/__init__.py b/homeassistant/components/fan/__init__.py index d4af7562920..13244569dbb 100644 --- a/homeassistant/components/fan/__init__.py +++ b/homeassistant/components/fan/__init__.py @@ -11,10 +11,10 @@ import voluptuous as vol from homeassistant.components import group from homeassistant.config import load_yaml_config_file -from homeassistant.const import ( - STATE_OFF, SERVICE_TURN_ON, - SERVICE_TURN_OFF, ATTR_ENTITY_ID) -from homeassistant.helpers.entity import Entity +from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TOGGLE, + SERVICE_TURN_OFF, ATTR_ENTITY_ID, + STATE_UNKNOWN) +from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa import homeassistant.helpers.config_validation as cv @@ -43,12 +43,12 @@ SPEED_HIGH = 'high' ATTR_SPEED = 'speed' ATTR_SPEED_LIST = 'speed_list' -ATTR_OSCILLATE = 'oscillate' +ATTR_OSCILLATING = 'oscillating' PROP_TO_ATTR = { 'speed': ATTR_SPEED, 'speed_list': ATTR_SPEED_LIST, - 'oscillate': ATTR_OSCILLATE, + 'oscillating': ATTR_OSCILLATING, 'supported_features': ATTR_SUPPORTED_FEATURES, } # type: dict @@ -68,16 +68,21 @@ FAN_TURN_OFF_SCHEMA = vol.Schema({ FAN_OSCILLATE_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(ATTR_OSCILLATE): cv.boolean + vol.Required(ATTR_OSCILLATING): cv.boolean }) # type: dict +FAN_TOGGLE_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_ids +}) + _LOGGER = logging.getLogger(__name__) def is_on(hass, entity_id: str=None) -> bool: """Return if the fans are on based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_FANS - return not hass.states.is_state(entity_id, STATE_OFF) + state = hass.states.get(entity_id) + return state.attributes[ATTR_SPEED] not in [SPEED_OFF, STATE_UNKNOWN] # pylint: disable=too-many-arguments @@ -102,12 +107,21 @@ def turn_off(hass, entity_id: str=None) -> None: hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) +def toggle(hass, entity_id: str=None) -> None: + """Toggle all or specified fans.""" + data = { + ATTR_ENTITY_ID: entity_id + } + + hass.services.call(DOMAIN, SERVICE_TOGGLE, data) + + def oscillate(hass, entity_id: str=None, should_oscillate: bool=True) -> None: """Set oscillation on all or specified fan.""" data = { key: value for key, value in [ (ATTR_ENTITY_ID, entity_id), - (ATTR_OSCILLATE, should_oscillate), + (ATTR_OSCILLATING, should_oscillate), ] if value is not None } @@ -180,38 +194,47 @@ def setup(hass, config: dict) -> None: return True -class FanEntity(Entity): +class FanEntity(ToggleEntity): """Representation of a fan.""" # pylint: disable=no-self-use, abstract-method - def set_speed(self: Entity, speed: str) -> None: + def set_speed(self: ToggleEntity, speed: str) -> None: """Set the speed of the fan.""" pass - def turn_on(self: Entity, speed: str=None) -> None: + def turn_on(self: ToggleEntity, speed: str=None, **kwargs) -> None: """Turn on the fan.""" - pass + raise NotImplementedError() - def turn_off(self: Entity) -> None: + def turn_off(self: ToggleEntity, **kwargs) -> None: """Turn off the fan.""" - pass + raise NotImplementedError() - def oscillate(self: Entity) -> None: + def oscillate(self: ToggleEntity, oscillating: bool) -> None: """Oscillate the fan.""" pass @property - def speed_list(self: Entity) -> list: + def is_on(self): + """Return true if the entity is on.""" + return self.state_attributes.get(ATTR_SPEED, STATE_UNKNOWN) \ + not in [SPEED_OFF, STATE_UNKNOWN] + + @property + def speed_list(self: ToggleEntity) -> list: """Get the list of available speeds.""" return [] @property - def state_attributes(self: Entity) -> dict: + def state_attributes(self: ToggleEntity) -> dict: """Return optional state attributes.""" data = {} # type: dict for prop, attr in PROP_TO_ATTR.items(): + if not hasattr(self, prop): + continue + value = getattr(self, prop) if value is not None: data[attr] = value @@ -219,6 +242,6 @@ class FanEntity(Entity): return data @property - def supported_features(self: Entity) -> int: + def supported_features(self: ToggleEntity) -> int: """Flag supported features.""" return 0 diff --git a/homeassistant/components/fan/demo.py b/homeassistant/components/fan/demo.py new file mode 100644 index 00000000000..83508063fa9 --- /dev/null +++ b/homeassistant/components/fan/demo.py @@ -0,0 +1,75 @@ +""" +Demo garage door platform that has a fake fan. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/demo/ +""" + +from homeassistant.components.fan import (SPEED_LOW, SPEED_MED, SPEED_HIGH, + FanEntity, SUPPORT_SET_SPEED, + SUPPORT_OSCILLATE) +from homeassistant.const import STATE_OFF + + +FAN_NAME = 'Living Room Fan' +FAN_ENTITY_ID = 'fan.living_room_fan' + +DEMO_SUPPORT = SUPPORT_SET_SPEED | SUPPORT_OSCILLATE + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup demo garage door platform.""" + add_devices_callback([ + DemoFan(hass, FAN_NAME, STATE_OFF), + ]) + + +class DemoFan(FanEntity): + """A demonstration fan component.""" + + def __init__(self, hass, name: str, initial_state: str) -> None: + """Initialize the entity.""" + self.hass = hass + self.speed = initial_state + self.oscillating = False + self._name = name + + @property + def name(self) -> str: + """Get entity name.""" + return self._name + + @property + def should_poll(self): + """No polling needed for a demo fan.""" + return False + + @property + def speed_list(self) -> list: + """Get the list of available speeds.""" + return [STATE_OFF, SPEED_LOW, SPEED_MED, SPEED_HIGH] + + def turn_on(self, speed: str=SPEED_MED) -> None: + """Turn on the entity.""" + self.set_speed(speed) + + def turn_off(self) -> None: + """Turn off the entity.""" + self.oscillate(False) + self.set_speed(STATE_OFF) + + def set_speed(self, speed: str) -> None: + """Set the speed of the fan.""" + self.speed = speed + self.update_ha_state() + + def oscillate(self, oscillating: bool) -> None: + """Set oscillation.""" + self.oscillating = oscillating + self.update_ha_state() + + @property + def supported_features(self) -> int: + """Flag supported features.""" + return DEMO_SUPPORT diff --git a/homeassistant/components/fan/insteon_hub.py b/homeassistant/components/fan/insteon_hub.py index 2f24bb0bc9b..4d65ee1f02b 100644 --- a/homeassistant/components/fan/insteon_hub.py +++ b/homeassistant/components/fan/insteon_hub.py @@ -64,8 +64,3 @@ class InsteonFanDevice(InsteonDevice, FanEntity): def speed_list(self) -> list: """Get the available speeds for the fan.""" return [SPEED_OFF, SPEED_LOW, SPEED_MED, SPEED_HIGH] - - @property - def state(self) -> str: - """Get the current device state.""" - return self.speed diff --git a/homeassistant/components/fan/services.yaml b/homeassistant/components/fan/services.yaml index 4f20e6036ce..e729e7f7e89 100644 --- a/homeassistant/components/fan/services.yaml +++ b/homeassistant/components/fan/services.yaml @@ -40,6 +40,14 @@ oscillate: description: Name(s) of the entities to oscillate example: 'fan.desk_fan' - oscillate: + oscillating: description: Flag to turn on/off oscillation - example: True \ No newline at end of file + example: True + +toggle: + description: Toggle the fan on/off + + fields: + entity_id: + description: Name(s) of the entities to toggle + exampl: 'fan.living_room' \ No newline at end of file diff --git a/tests/components/fan/__init__.py b/tests/components/fan/__init__.py index 251a118e32e..463e96a4319 100644 --- a/tests/components/fan/__init__.py +++ b/tests/components/fan/__init__.py @@ -1 +1,39 @@ """Test fan component plaforms.""" + +import unittest + +from homeassistant.components.fan import FanEntity + + +class BaseFan(FanEntity): + """Implementation of the abstract FanEntity.""" + + def __init__(self): + """Initialize the fan.""" + pass + + +class TestFanEntity(unittest.TestCase): + """Test coverage for base fan entity class.""" + + def setUp(self): + """Setup test data.""" + self.fan = BaseFan() + + def tearDown(self): + """Tear down unit test data.""" + self.fan = None + + def test_fanentity(self): + """Test fan entity methods.""" + self.assertIsNone(self.fan.state) + self.assertEqual(0, len(self.fan.speed_list)) + self.assertEqual(0, self.fan.supported_features) + self.assertEqual({}, self.fan.state_attributes) + # Test set_speed not required + self.fan.set_speed() + self.fan.oscillate() + with self.assertRaises(NotImplementedError): + self.fan.turn_on() + with self.assertRaises(NotImplementedError): + self.fan.turn_off() diff --git a/tests/components/fan/test_demo.py b/tests/components/fan/test_demo.py new file mode 100644 index 00000000000..db894ee54ed --- /dev/null +++ b/tests/components/fan/test_demo.py @@ -0,0 +1,84 @@ +"""Test cases around the demo fan platform.""" + +import unittest + +from homeassistant.components import fan +from homeassistant.components.fan.demo import FAN_ENTITY_ID +from homeassistant.const import STATE_OFF, STATE_ON + +from tests.common import get_test_home_assistant + + +class TestDemoFan(unittest.TestCase): + """Test the fan demo platform.""" + + def get_entity(self): + """Helper method to get the fan entity.""" + return self.hass.states.get(FAN_ENTITY_ID) + + def setUp(self): + """Initialize unit test data.""" + self.hass = get_test_home_assistant() + self.assertTrue(fan.setup(self.hass, {'fan': { + 'platform': 'demo', + }})) + self.hass.pool.block_till_done() + + def tearDown(self): + """Tear down unit test data.""" + self.hass.stop() + + def test_turn_on(self): + """Test turning on the device.""" + self.assertEqual(STATE_OFF, self.get_entity().state) + + fan.turn_on(self.hass, FAN_ENTITY_ID) + self.hass.pool.block_till_done() + self.assertNotEqual(STATE_OFF, self.get_entity().state) + + fan.turn_on(self.hass, FAN_ENTITY_ID, fan.SPEED_HIGH) + self.hass.pool.block_till_done() + self.assertEqual(STATE_ON, self.get_entity().state) + self.assertEqual(fan.SPEED_HIGH, + self.get_entity().attributes[fan.ATTR_SPEED]) + + def test_turn_off(self): + """Test turning off the device.""" + self.assertEqual(STATE_OFF, self.get_entity().state) + + fan.turn_on(self.hass, FAN_ENTITY_ID) + self.hass.pool.block_till_done() + self.assertNotEqual(STATE_OFF, self.get_entity().state) + + fan.turn_off(self.hass, FAN_ENTITY_ID) + self.hass.pool.block_till_done() + self.assertEqual(STATE_OFF, self.get_entity().state) + + def test_set_speed(self): + """Test setting the speed of the device.""" + self.assertEqual(STATE_OFF, self.get_entity().state) + + fan.set_speed(self.hass, FAN_ENTITY_ID, fan.SPEED_LOW) + self.hass.pool.block_till_done() + self.assertEqual(fan.SPEED_LOW, + self.get_entity().attributes.get('speed')) + + def test_oscillate(self): + """Test oscillating the fan.""" + self.assertFalse(self.get_entity().attributes.get('oscillating')) + + fan.oscillate(self.hass, FAN_ENTITY_ID, True) + self.hass.pool.block_till_done() + self.assertTrue(self.get_entity().attributes.get('oscillating')) + + fan.oscillate(self.hass, FAN_ENTITY_ID, False) + self.hass.pool.block_till_done() + self.assertFalse(self.get_entity().attributes.get('oscillating')) + + def test_is_on(self): + """Test is on service call.""" + self.assertFalse(fan.is_on(self.hass, FAN_ENTITY_ID)) + + fan.turn_on(self.hass, FAN_ENTITY_ID) + self.hass.pool.block_till_done() + self.assertTrue(fan.is_on(self.hass, FAN_ENTITY_ID)) diff --git a/tests/components/fan/test_insteon_hub.py b/tests/components/fan/test_insteon_hub.py index 270687c9fd3..dfdb4b7a9f0 100644 --- a/tests/components/fan/test_insteon_hub.py +++ b/tests/components/fan/test_insteon_hub.py @@ -1,8 +1,9 @@ """Tests for the insteon hub fan platform.""" import unittest -from homeassistant.const import STATE_OFF, STATE_UNKNOWN -from homeassistant.components.fan import (SPEED_LOW, SPEED_MED, SPEED_HIGH) +from homeassistant.const import (STATE_OFF, STATE_ON) +from homeassistant.components.fan import (SPEED_LOW, SPEED_MED, SPEED_HIGH, + ATTR_SPEED) from homeassistant.components.fan.insteon_hub import (InsteonFanDevice, SUPPORT_SET_SPEED) @@ -50,27 +51,23 @@ class TestInsteonHubFanDevice(unittest.TestCase): self._NODE.response = { 'status': 'succeeded' } - self.assertEqual(STATE_UNKNOWN, self._DEVICE.state) + self.assertEqual(STATE_OFF, self._DEVICE.state) self._DEVICE.turn_on() - self.assertNotEqual(STATE_OFF, self._DEVICE.state) + self.assertEqual(STATE_ON, self._DEVICE.state) self._DEVICE.turn_on(SPEED_MED) - self.assertEqual(SPEED_MED, self._DEVICE.state) - - self._NODE.response = { - } - self._DEVICE.turn_on(SPEED_HIGH) - - self.assertNotEqual(SPEED_HIGH, self._DEVICE.state) + self.assertEqual(STATE_ON, self._DEVICE.state) + self.assertEqual(SPEED_MED, self._DEVICE.state_attributes[ATTR_SPEED]) def test_turn_off(self): """Test turning off device.""" self._NODE.response = { 'status': 'succeeded' } - self.assertEqual(STATE_UNKNOWN, self._DEVICE.state) - self._DEVICE.turn_off() - + self.assertEqual(STATE_OFF, self._DEVICE.state) + self._DEVICE.turn_on() + self.assertEqual(STATE_ON, self._DEVICE.state) + self._DEVICE.turn_off() self.assertEqual(STATE_OFF, self._DEVICE.state) From 43555b646c27f5e1d9e14c966ad85150a84138c1 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Sat, 27 Aug 2016 20:05:44 -0700 Subject: [PATCH 192/193] update frontend --- homeassistant/components/frontend/version.py | 6 +++--- .../components/frontend/www_static/core.js | 8 ++++---- .../components/frontend/www_static/core.js.gz | Bin 32126 -> 32161 bytes .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 124422 -> 124422 bytes .../frontend/www_static/mdi.html.gz | Bin 174430 -> 174430 bytes .../panels/ha-panel-dev-event.html.gz | Bin 2639 -> 2639 bytes .../panels/ha-panel-dev-info.html.gz | Bin 1308 -> 1308 bytes .../panels/ha-panel-dev-service.html.gz | Bin 2824 -> 2824 bytes .../panels/ha-panel-dev-state.html.gz | Bin 2772 -> 2772 bytes .../panels/ha-panel-dev-template.html.gz | Bin 7290 -> 7290 bytes .../panels/ha-panel-history.html.gz | Bin 6842 -> 6842 bytes .../www_static/panels/ha-panel-iframe.html.gz | Bin 403 -> 403 bytes .../panels/ha-panel-logbook.html.gz | Bin 7344 -> 7344 bytes .../www_static/panels/ha-panel-map.html | 6 +++--- .../www_static/panels/ha-panel-map.html.gz | Bin 43913 -> 43920 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2274 -> 2285 bytes .../www_static/webcomponents-lite.min.js.gz | Bin 12355 -> 12355 bytes 19 files changed, 12 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 78bd44c1c96..5fce36f45b1 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,8 +1,8 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "1222f00ae060652376f7ff0b48470e43", - "frontend.html": "fa112bdd88ccf8aef7548c8f56b4ac82", + "core.js": "1fd10c1fcdf56a61f60cf861d5a0368c", + "frontend.html": "88c97d278de3320278da6c32fe9e7d61", "mdi.html": "710b84acc99b32514f52291aba9cd8e8", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", @@ -12,5 +12,5 @@ FINGERPRINTS = { "panels/ha-panel-history.html": "efe1bcdd7733b09e55f4f965d171c295", "panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab", "panels/ha-panel-logbook.html": "66108d82763359a218c9695f0553de40", - "panels/ha-panel-map.html": "49ab2d6f180f8bdea7cffaa66b8a5d3e" + "panels/ha-panel-map.html": "af7d04aff7dd5479c5a0016bc8d4dd7d" } diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index ce03134e0b7..336aab04ffe 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&&"object"==typeof t&&"default"in t?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 je({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ne.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 Ue({authToken:n,host:r})}function u(){return Pe.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 Ke.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?$e({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||$e;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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return Dn.getInitialState()}function C(t,e){t.dispatch(wn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:Dn})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[er(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[bn.byId(t),tr,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return pr(n)}function P(){return _r.getInitialState()}function H(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 vr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return yr.getInitialState()}function V(t,e){t.dispatch(hr.SERVER_CONFIG_LOADED,e)}function q(t){fn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(hr.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:_r,serverConfig:yr})}function Y(t,e){var n=e.pane;return n}function B(){return Dr.getInitialState()}function J(t,e){var n=e.panels;return zr(n)}function W(){return Rr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Mr.getInitialState()}function Z(t,e){t.dispatch(Tr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(Tr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(Tr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return qr.getInitialState()}function rt(t,e){t.dispatch(xr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(xr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return Yr.getInitialState()}function st(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Jr({})):t.withMutations(function(t){r.forEach(function(e){return t.setIn([n,e[0].entity_id],Jr(e.map(dn.fromJSON)))})})}function ct(){return Wr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,$r(e.map(dn.fromJSON)))})})}function ht(){return ti.getInitialState()}function lt(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(ri,r)})}function pt(){return ii.getInitialState()}function _t(t,e){t.dispatch(Gr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),fn(t,"GET",n).then(function(e){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_START,{date:e}),fn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ai);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:Yr,entityHistory:Wr,isLoadingEntityHistory:Qr,recentEntityHistory:ti,recentEntityHistoryUpdated:ii})}function gt(t){t.registerStores({moreInfoEntityId:qr})}function mt(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;oru}function ae(t){t.registerStores({currentLogbookDate:Fo,isLoadingLogbookEntries:Ko,logbookEntries:Qo,logbookEntriesUpdated:tu})}function se(t){return t.set("active",!0)}function ce(t){return t.set("active",!1)}function fe(){return du.getInitialState()}function he(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",fn(t,"POST","notify.html5",{subscription:e,browser:n}).then(function(){return t.dispatch(lu.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),Mn.createNotification(t,n),!1})}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){return fn(t,"DELETE","notify.html5",{subscription:e}).then(function(){return e.unsubscribe()}).then(function(){return t.dispatch(lu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})}).then(function(){return!0})}).catch(function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Mn.createNotification(t,n),!1})}function pe(t){t.registerStores({pushNotifications:du})}function _e(t,e){return fn(t,"POST","template",{template:e})}function de(t){return t.set("isListening",!0)}function ve(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 ye(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 Se(){return Ru.getInitialState()}function ge(){return Ru.getInitialState()}function me(){return Ru.getInitialState()}function Ee(t){return Lu[t.hassId]}function Ie(t){var e=Ee(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Du.VOICE_TRANSMITTING,{finalTranscript:n}),ir.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(Du.VOICE_DONE)},function(){t.dispatch(Du.VOICE_ERROR)})}}function be(t){var e=Ee(t);e&&(e.recognition.stop(),Lu[t.hassId]=!1)}function Oe(t){Ie(t),be(t)}function we(t){var e=Oe.bind(null,t);e();var n=new webkitSpeechRecognition;Lu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Du.VOICE_START)},n.onerror=function(){return t.dispatch(Du.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ee(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:L(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 L(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 M([]))}function H(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){ -return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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 Me(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),Ce=t(De),ze=e(function(t){var e=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};t.exports=e}),Re=t(ze),Le=Re({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Me=Ce.Store,je=Ce.toImmutable,Ne=new Me({getInitialState:function(){return je({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)}}),ke=Ce.Store,Ue=Ce.toImmutable,Pe=new ke({getInitialState:function(){return Ue({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),He=Ce.Store,xe=new He({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),Ve=Re({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),qe="object"==typeof window&&"EventSource"in window,Fe=Ce.Store,Ge=Ce.toImmutable,Ke=new Fe({getInitialState:function(){return Ge({isSupported:qe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ve.STREAM_START,s),this.on(Ve.STREAM_STOP,c),this.on(Ve.STREAM_ERROR,f),this.on(Ve.LOG_OUT,h)}}),Ye=Re({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Be=Ce.Store,Je=new Be({getInitialState:function(){return!0},initialize:function(){this.on(Ye.API_FETCH_ALL_START,function(){return!0}),this.on(Ye.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(Ye.API_FETCH_ALL_FAIL,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),We=Ce.Store,Xe=new We({getInitialState:function(){return!1},initialize:function(){this.on(Ye.SYNC_SCHEDULED,function(){return!0}),this.on(Ye.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),Qe=Re({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}),Ze=Ce.Store,$e=Ce.toImmutable,tn=new Ze({getInitialState:function(){return $e({})},initialize:function(){var t=this;this.on(Qe.API_FETCH_SUCCESS,l),this.on(Qe.API_SAVE_SUCCESS,l),this.on(Qe.API_DELETE_SUCCESS,p),this.on(Qe.LOG_OUT,function(){return t.getInitialState()})}}),en=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c199&&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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return Dn.getInitialState()}function C(t,e){t.dispatch(wn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:Dn})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[er(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[bn.byId(t),tr,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return pr(n)}function P(){return _r.getInitialState()}function H(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 vr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return yr.getInitialState()}function V(t,e){t.dispatch(hr.SERVER_CONFIG_LOADED,e)}function q(t){fn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(hr.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:_r,serverConfig:yr})}function Y(t,e){var n=e.pane;return n}function B(){return Dr.getInitialState()}function J(t,e){var n=e.panels;return zr(n)}function W(){return Rr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Mr.getInitialState()}function Z(t,e){t.dispatch(Tr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(Tr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(Tr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return qr.getInitialState()}function rt(t,e){t.dispatch(xr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(xr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return Yr.getInitialState()}function st(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Jr({})):t.withMutations(function(t){r.forEach(function(e){return t.setIn([n,e[0].entity_id],Jr(e.map(dn.fromJSON)))})})}function ct(){return Wr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,$r(e.map(dn.fromJSON)))})})}function ht(){return ti.getInitialState()}function lt(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(ri,r)})}function pt(){return ii.getInitialState()}function _t(t,e){t.dispatch(Gr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),fn(t,"GET",n).then(function(e){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_START,{date:e}),fn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ai);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:Yr,entityHistory:Wr,isLoadingEntityHistory:Qr,recentEntityHistory:ti,recentEntityHistoryUpdated:ii})}function gt(t){t.registerStores({moreInfoEntityId:qr})}function mt(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;oru}function ae(t){t.registerStores({currentLogbookDate:Fo,isLoadingLogbookEntries:Ko,logbookEntries:Qo,logbookEntriesUpdated:tu})}function se(t){return t.set("active",!0)}function ce(t){return t.set("active",!1)}function fe(){return du.getInitialState()}function he(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",fn(t,"POST","notify.html5",{subscription:e,browser:n}).then(function(){return t.dispatch(lu.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),Mn.createNotification(t,n),!1})}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){return fn(t,"DELETE","notify.html5",{subscription:e}).then(function(){return e.unsubscribe()}).then(function(){return t.dispatch(lu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})}).then(function(){return!0})})["catch"](function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Mn.createNotification(t,n),!1})}function pe(t){t.registerStores({pushNotifications:du})}function _e(t,e){return fn(t,"POST","template",{template:e})}function de(t){return t.set("isListening",!0)}function ve(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 ye(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 Se(){return Ru.getInitialState()}function ge(){return Ru.getInitialState()}function me(){return Ru.getInitialState()}function Ee(t){return Lu[t.hassId]}function Ie(t){var e=Ee(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Du.VOICE_TRANSMITTING,{finalTranscript:n}),ir.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(Du.VOICE_DONE)},function(){t.dispatch(Du.VOICE_ERROR)})}}function be(t){var e=Ee(t);e&&(e.recognition.stop(),Lu[t.hassId]=!1)}function Oe(t){Ie(t),be(t)}function we(t){var e=Oe.bind(null,t);e();var n=new webkitSpeechRecognition;Lu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Du.VOICE_START)},n.onerror=function(){return t.dispatch(Du.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ee(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:L(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 L(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 M([]))}function H(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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 Me(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(n){}}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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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(c){throw A["default"].dispatchError(t,c.message),c}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var h="Store handler must return a value, did you forget a return statement";throw A["default"].dispatchError(t,h),new Error(h)}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),L=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}])})}),Ce=t(De),ze=e(function(t){var e=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};t.exports=e}),Re=t(ze),Le=Re({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Me=Ce.Store,je=Ce.toImmutable,Ne=new Me({getInitialState:function(){return je({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)}}),ke=Ce.Store,Ue=Ce.toImmutable,Pe=new ke({getInitialState:function(){return Ue({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),He=Ce.Store,xe=new He({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),Ve=Re({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),qe="object"==typeof window&&"EventSource"in window,Fe=Ce.Store,Ge=Ce.toImmutable,Ke=new Fe({getInitialState:function(){return Ge({isSupported:qe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ve.STREAM_START,s),this.on(Ve.STREAM_STOP,c),this.on(Ve.STREAM_ERROR,f),this.on(Ve.LOG_OUT,h)}}),Ye=Re({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Be=Ce.Store,Je=new Be({getInitialState:function(){return!0},initialize:function(){this.on(Ye.API_FETCH_ALL_START,function(){return!0}),this.on(Ye.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(Ye.API_FETCH_ALL_FAIL,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),We=Ce.Store,Xe=new We({getInitialState:function(){return!1},initialize:function(){this.on(Ye.SYNC_SCHEDULED,function(){return!0}),this.on(Ye.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),Qe=Re({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}),Ze=Ce.Store,$e=Ce.toImmutable,tn=new Ze({getInitialState:function(){return $e({})},initialize:function(){var t=this;this.on(Qe.API_FETCH_SUCCESS,l),this.on(Qe.API_SAVE_SUCCESS,l),this.on(Qe.API_DELETE_SUCCESS,p),this.on(Qe.LOG_OUT,function(){return t.getInitialState()})}}),en=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(o){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;cHh2nefG!dC(VV{dY0E^2cC)V*tW+qSX*`u+Y2S*yo~+=f*t zZMt_UGdhm#G)^2l^&@Gwmyb3rK{gv1R7fg`W9z@)nZbhqAF`Zw?{n{JS1giv33Dg0hvZ+|D3e{d)ehWYJ`Clh)% z=96eX&D${)8RX~Y`69>{rXlX-jGLx-c*noYk~GhPyTyX#9%sCx-uT7OqPmdPKSgOv zguD~Y^Xt>(0~aiXr|Trk`>N$XxOZp127=+YAZ2m(E}F*UD38Teu-1j=eent31ZzFU z(=! z4SgSL&%+q%%%;(Z555EPS@=PY9eat-qHsG+quWlL(O)n12WfDgUa$`!ncM$ zYZ|^Ba{&*~ZSsll3-4Sbfu+#kh1J#&p^^~YEp$!ZiNy$sUgWz`9))HEoWZh#@<}{y zb;B@B*VnxiD*9{;-*T2Btc+`%KCZG5FaglSoqwtg91gze25}^n_WZjms(J@3Pyi{h zyffkX=o(t)@>i+28lZteKuJL`@Xk2SW)W2Je&wC*xBJ5vd#5`uhbO1o$EWO$kR0Sp zq8PZ#4bQKWanPn-fZOV>sh>`M&4oAaT*hMTiTQNOXn;QZRC(o7-&A#bI{nXp3msVy z!++B3k3TV(lkInVdMtVj1TnU2L3>+8@kuR;X-A*(oVPC! zzT)Xm0J*z&uys1xjn|g96mgg9kx?DGARX0rh+0M@1$%&qNUQE4YintT9 zv}pO$$}PXx-an{qHp&t~&AtV07-zUjQGc!iPFZwwyFxc|vL6Zm$*K+iDe$jW=tYyk zBL{G^deeVu2zzovPWe@wKiZ(u5Z3zCkwTp5^ZhwvZ zw3w69Hib*nCz&A*p>Ysk=U90=A%S#XOh95tK$<|IbEExzG>gA)Z-~CtnVKR?96){} zr4ao7+na-zc|JSlALlTX{=AdSI5MRK#Uv0aKpartUh-(nQ?LEo=F9EPXfy)3xy|B2 zGRD%0m?qIUv{WP7_3=KX9KHBcfwKBo9kpU??CO&9i5{pMPFo*H2qNbh`sk zq5J@+bwNWQwZI;OMkf&mO9x&ZT6Pr3rwB5u47ESHM)>pa?DWOvKiU$tz<-2kXs9}h zt9XLqo{wXqPmYwjU6Q`a>Jf@<@NfJTIe$@Yw*Y@vEE8^bWcwB~_$)eyN2mKQ_II{V z_m2*TJI8z5r+d4=5tO#aZTP;{uXmB;@kHSv3wE6ae=NHM0l7U*MjwzEawRCQby03^ zUjfg#;=^$QV!QiQ;{m1S+<)(DP5}F+092%(Vj#~Bi2Pm~KMaA?td0+CeHz#YEVcGk zn#^a^NoSngM6npOC4J^ZDg6GvolGXyivYk^MWHdP^*46w=Rg{{U(dDH*K-$E?y#Oe zEJk)II+wTmV{9r<*@0E+Q1T9t@olvm(K8A?&24G;;0Ghj3^yqbrJWJ)k%VoSg%<}6}aAK!){iD6-{ z+m&2vWG|z6m|w@J8%62W9HsmWw4FK_RaKbGwOCU)c3y@T1i}&YR|3<3$TFi^j5?z! zkDNsvLrr?A8;oIuvVY=&jS2*Ra2MVvxdEO6z!ytzHqWj-d(oXWR53czEOpAiEf(o8 zUA9PHx(!cZS>^LFCoOE600*I`n4aXC8;a-#m^r-3`OS={!1Gc*oJ0G7CwK{CAASYk zU?zCy6Hha!qoMqidUv`D*!N8bLCT!wgP4^Y4-#gY4(1H0oPVe9Wb;8}Gl4I~*l(AP z{auAYU8kLsz2kR#$HSeY!x#I%3=fXBcY#51tJX(Se{t7q|FU-qd>M9@Nqp5-!f|y= zSN+%^zNqVY=jhGbqr<(!Q{C&GnP!(U{^H0Z5)(VRXxoxREDK);_dj4PXyUP1!s~h_ zTWT~IrcA%W!G8v~jydXgmxyMO;5F8z=hnutbY5Ono0}R!|LPL@`=Zg~rH%gPHkw^0 zp9>ye6#KPk@6FQo{#lvAQy`v~NAHIx`@4J3w~yH!_TkRlcXgExx8Lpm0{b9pUZS)I z=6PL>x7&w%2PcM1B!b+EJTF;5Ns8Pb*UXE^i!py(I)CQ03e6W>F$a4)r$Zpz{nOvs zo$kqnC(b3Itx^#=reip@%-(AtQ`c@n`Lmz+kCuhBH2yIZH)HSQ$^OaF35iIKwba7I z?@KX})ih5$lQ!~~u$GeaR`*B3x3Z88lsSyON>TPhGu;w1bZ3&Jd!Pu^aTRKaOk#|m zcQ4co4}atF1-1?HTr~5>g@F&ZSJ&=p4fg%g!A?qptsCRAVTcEZ;khGV->ou$Yij^` zywuFPWB@R0wF1MxWn3v*MXqJXiXfi#q|gT9M@-)>^Qbkzc+K~%u_;UZ` z^yv8a;qEpn_q67aYaq$GYjmv9q%}q_9_rqS&l6 zg?}o`ESA?xCZlqGpb+-Fwj5g<7L0a*+~2Pmr%&Mx z(vF!V?Dmr_z3udqjSU|fOwSXGA6W`;D}T3_rDb%ha+d8_@7(Y9_ujL+PcbivIs18| z`3X%xq7&t?_g>C(&{7RBRc0zklV8h8lNG+iTC7xb;rC zc&v2m^>qM6ff%DV54}>BwQo7$y~EM&IJ9tNyX8N|=LB%JKeoi|&(6F{K`+<3WPh8M zUPhJxWQHBYXvpvHCFiw7wNr%Pdbl^qtP8APoWlP%%tlgM`M@ z^WFt)F_%PO7T=KqGlMxhi(yWue1Ak;lF1RKKyRgL707+@b56br_AX|p@~3URsuKlZ z0SZzxP+ceN_pQ->j&VMBY`(KU_6HtKdndjUKp%(vOTNn`fU*csIy(ZAb6!FPKS;^q zV`F!HJ$B!f5PW~%fEt(>xxRoc#8n){4inxX8i2X~68m>V5Pjt@Z5jhcV}Hz&8R2N> zIucj>0GEW|X|S7H9-rK2bMYAgJd8fYS2XiSmr`K_0XLC9VWf`LDhHtT1X33?1?%hj z9U4K*jONTOij$ItE0D1g-X)1=<_6UDSYAOLi`l zgDN~uhX_RD5)XJI?GE@7vVZOcmdUItB4_|EqtOQtQ5i)>^lh#fat%~89`AjE(P^sk z+M3$h46s#8dA{Wa`D#lmr)wLab%1GCrYefDkIyO_J#^kQGePmC0MN(bV0O> zzPCX=^bSj_{Z;Jy%r4{EJoXPu+OrGcv~X!QwUw7c7hWT0{BHYhw+{{q#ljJbFOwvP zoh6#pS>S5;=Dx6_I&e3TizV|}oK`<6Yr4-~SL<=40r+&8cBByyrAq|BK4D@~sf`5^dJVdvle>aLUE~T#F zh!*#_9gy)S>InXMNM8m(U{2H#O}Sgf4~PnNC{R(tNW*^rGUd^SKJ{qqz{4pKQ9B@t zQ!g#TqBhJ2rwv8OLyaG71?XM9J~nTQcC;r-KB)B0kqbCI~~93y8GhF|h%nqTi+ z^U(*r_;Fz+^M7=N+#ty~ys+yNZ!E0zE6^j%=aEnpxswP1R9zuTP&~dEp(h2V_O8U# zI69lw#m^|q<&nRMW06&K_7}w_{MT^9tIeYjhV~4jCehGCgtWd+E6no0%lH10wz-V5w1o{1 zO9Fz&wb`FkC_IA;*Rx?<#P{`gauMW{N5y&I3cJx*uElPcm zX|HxrtQ&ryO=gb;)`ic~!6ebM!S3qV0;n_#KYu9Z3`)71Ss=;Wrs5@>M+Z%mCTy0J z5w(9<9g!30E?kS*>+)6zZ5$l^GCVpX3CQxjHP9KNYdc3TY91VNhL1{@2;OoRb6*@P ze2!LUw7XCY1sa$5zXX`J&+6sxSYS4lO8SKgq{rTs&cpAU6Tstq4Wv-o^H+ULh=xNL|H(pDy-x4n+ zWV}io*ID5i=0(?kzb@@s@aB=}?&^GJw#V4&ET1nuvBN8d=64CQyyr(puOIeZB}=RC z9iATV@13mRWP!;Ah4RD7-j(J~O70akT`PE28k?+jt<3pK&hd0^xw-jLW5a<&0XbD( zB!v$}z28#sTR5o5pW!H9- zLK=n=qXoTB(hoe9(W8i(G?J54B7|J|CH(w4O+HghES&@L+J{L?HP!k|ZM6z@tJC(~ z0IxTZfSocW%lHTw8u#u%xJ%!~Sq!Z3NK9`PH?5jAXhj+(6BYx(2DYzY5`pm?B%gV@ z6QOzq3h9`Ce>sAkY!at@l6-0V&o+Al^Axm4Fq9jV-f1noJvza~K%thmo$LH&`V{!J z0(6E@07YNI;GsLD=!!5`rRwRt^Y-lI<xOnD8qV7!9JDW% zp~8q{XlhbFi_u?=ZiW~L%Tw4g+CFFvh=sSHl;UZBOK4-(0tj06xLdPnl*5L4(*Z0U zTCt~UY9)=dCQ&@aIc6i++mfj|a){!=8_^koyq8DD2%qgpT}YxSM}SqcT=b;n?(My}6wT5%2~K_M0ZXMA&-MnXjW{cAfXsFW@$pvvaz^cRuWtu<0@hnZ`85CF*U-H_Gt*+7D}mY_)&H9jj(v2gM72 z(xpH1%MWpWGUI%7eO&b3ce=f^;0gq*OiR!P`JsgOc6-5up21^^ammm%E;_Jc&;%1M zW#$HZ(n7hQdQGQkmSA1h6XTH6FBxnTR++n@NKqVdPD2=1jQ=DiPG=t_ihi=CpEEno z#=OK}n>c%cC>f+1q5U4?0`me*@v^UfeNkNkVGIK)A$ucCSsf0J_fF0ZK;fxQSX`N} zN~1`yOek}ieZp+H67ep9CAO2?+(cp=9M3W11HLg9$zU5dD@5-$58HDgEd}HDnl?^I zqtZbB3F=B*O_NJNto&13BIDD^0RIW@7HpS?&Y3ls^R+^^!%(G4It^ZzVq=hh>wFkt z>iI#9T}8sNzApcEqMPwR{`Af-pr4@H&wzIh=kh!WwkhnVg}2RX6h`MTev#HACHW5x zS30l@e`|>QgW=4742 zzX{1H8lpdGhHHs?AVGNN_Jovw&Kxi7Z*AhNUDPq= zCV3X$>lur<_XOQLDIV6D!_!abkV(C{kLeM-AAB}~r_5&)czWuyYxvXa`D}`RyFQ!2 z-@p582!&?ARIPL?;oUI@Z8b@Q$a>3Yodk*fYX9a2WC%2WjqKNP_L|>+zK!zh;JRae z!&_-Z45l6ZljX^)lVH-pKk&O~4qurkOtNBqv7VR|Lb-imQ65+hoFioT^e;lWF#J?%sSB>NUFhE~)XO<_xHMex5_hiy0eOhLPL z>!U}Ls`AHJW3-b2;TZHbCBklBz=otYBB3*JfarZLF8XPwFtdjC!~OkQkLdu0x%>`` zxlJ&j{h54AozH2Ut8YupyJ%ELVR}(H;Ora_7qFl~&H;HVPml+HqSlkrI}B;#iv4#Z|3X3cB%E6mu2un8)Y*4h9;ui_dK)=gc8SCQFqB=9;3i z)RjP2s%SqU&2MRcd}Q(FTBEPopVEO8gcX7qo;F1`>U0UR8qcf!7IclBR#gGr2+Gq{ zn1M@_=AsOHrVcKdhB6RY>M@*Kc*}_S`6&JBiWqshYE{DuWeXSRiSkP9oQNb(UJy^e z^}Uf_vZ~2TR`%Bp3Vi|p)K%u2oDb!Ftf z3D8BRw-s&*47e*?%5DMvEEH~TEX#y*O&xUIG**@G+(|^`fMg+bAc7pmX3ZYo$o-&z z3xq8BF-Bs}-K14TgYX+l?l@}a%qnmz3w(7746OoxC$hk?Q(#=`Vtsw>N|rlt%6+nY zA0B!?*7EbQxNy_9R7!kuN}SY`xOGZgmBw>_f8s!KQ`5qU(}GN0f~-!!He)Z+ee0wI z$)j?1c+gX`bPivObpo7QuGBb4L+zJkV>}ZLa=V?C<Ryu5h@8YD+TyTXq)}+e$WPjH+zb@vR1hqReOw{u`{LsMK0m(%1kwVn_GuO? zx3f~Xkg8>G!6|u@lb)iGN6a}JYlXZ8O-#}^u>BMM5gy+;;D24A1*i&=J0HvX)ZDGx zW=?Ke^qAes7cZSoj#ma#wabf^uoJRW=>ETdI87f|`{1LSrnY<n=~kAC{5Iip&7wk!?tASvNAok0G~OMf;IqR3tb7comA@rR?Y6eR=C+wXDgs2gcGL9!M^hiv9{-or%9-D*QHs1=9{#>h*Q5c_#L9#gy<`f$R z0vMj%N(a$-_ac~sqyVgAt*2S^e50pjsrkYPqegl=69mH8b8`&+@&K&0a9Sy<_PkQQ zsN9CyfVS~08Nfan?4#Z}$Y}u3SPlb1LwyC@ByE8AHQM}%9xPhe#shDlEwr6~Oc}OJ z{oHwagjMWag_4G(+ z7Md*1=ktRQ&Ff=B2us2f%%KdE5SUu6BlPMh` zf4U`4OhX;h)D9HgL3@ncJ!_(O#3orNDFR1H3|T8mDO#xoyeIh#l0=lDNReTz8MF>K zXtLD45twkNh`a4E+W?Hu+Te@7r3T3t67ZG{_~X!9W-yi&tFE};&`OQ(7e(~d8&=uf z$RcNQ$5GuJmH8HF9G@jKF zz04?%AuPO-AvMhPCyUsvzM9(9weavZ#|~h#32P6Y#$q&`k2z(TWZXQ~7gpIQ(Fu$a zv%z;?uWAsbe>Ajucp!6OdW1FPrVEvOy(-3+IwB?>hI>VyRvjwx zfRd4tHO!MLBCaLDi`gJ13OYu=_-Wo!_6z+J7=W4JS}la2yb*&d5!?tlI45hA;~jEH zEOiJgZJt{_T@-Oz6iJ!UzU2J^DVr8pNdT;=7{r0H^$C`Mq?=PSOD5TFfArx=j@jJ6 ziD|-APx1r&ljup0oqp>k-5HIA-aX75vvjKCFtMgOmNTtWb(tF(XhK;O&T-b&*L~fio<|JnX!n1e*OxELTVcx8ogwR2E*mh6`_feQnJUR;*TD{HO)2+9|EyK|-f1 z<7JB&7oJK2E~To%BGZ7}gk_TD7E2gk>17mw5`s?06nc-)!~=uDf78+n3y!))Z39wT z)O6Uo*-(UvO~0?vGq)Ca;w0lJ# z$R+>`Mys&6oGz{)&@<@06J>9tYue69Sc6X*cG{WKksHqCZfMvo5brO=7- zfP1C1Z8kt?iePc*f1$%`fC2ddg6P6n3tWOcJFWnSiJogyS;JNe+Wa|gij)dD9h}cu zauMLMS_D}|#T?j6CU$Ku1)spYM=T-ZQ7OM%*~W-Gv~MdnQdjQYb4%%yCw#m2!e<$U zwZy)A7f%w7;C+m=HlZA3L_tt9xxbI#Po#?@2-*!~GcUBce-U8R+%=nq(Pq*|6UP+# zz7D5b-9a}{S^Q@%3Q90zI z`};KyHsXzqf33t!R|e~l6NeE&1{@}qlEeCXhUuRcnC;sd+cK#U>Ee2QeU)KoK~i~p zWyOk|$>b0p;8ir7z8_nhYGWgMW^j9{V!ZRv6w&+3{k@VQ^8kNbi2)kHk{F zJk4m=3Shmg_1LB7mj%`MpKN((<>BWLM5QpU)4n1B{DGAU-z z!e3p;e|W?&V9Kp=)QBf^He&RUGYdvA>5mg>S&tMYFqaHqg~xh@$9jdwYy`u#SGauR ztZ=#OX!_|V;kA@*uJLn5w%R4z!qeT(E9p`SBMAkLM2xr_ib8ebAtqANheU`guKw6e6J%c zFit%I#Vg8lEs3Z)EV!?U$Lp ze@2AXOcT#GF)3^O{yy8{fJK^eYGI@22gtM0$^hFRtmIJc*~qN`^0kN*e@jZ}^{u$w z?jzZJnTf-`3{vTX8*|dv7NMlVr=@}aPO1=kkzs0HS~9e}P>-O%=% z2c_O9Xx2@e+i2ggtQzau*I6IcCT1_mpU&<%cC8myq9iSO^{|MkSDv`m_Yn6fh=>HpUgVCRD262NS7f9j_; zIZ0cRDCZx>S%ozPD$SwEgQj%4E`eG*yS%{Cd5Srcp(8P%_qd1f3p^&7NRC@r5;|Fu z=8d+L^B*plfPXNx?fH|7O#%Nbio`YPz~yAgIloW~A$+n3svkp)*`NeaUts|d`y3qO zuLJm}oIhEcdNn32lhDH$fZA&0e+Y1u?-s+{#^VeK7mO6vGe+DlYy%H&91F|p{!mNs zLblX8@HM}A$%?Tifq5*=37Eb!GH&j&(`tqnH0R};gim0l*yI{$DO}st#=o#d_J3U z8TD4qg!}(!BcQ&54zTRTAg<=+AoH1A^}}FX&T^|txyLCys`OQ{ir~Pvj#oITY?E0g z9e-zYN=b6v26!o!1 zTm*iNcls=UC`=iXw*_xyzTveSDVpQErW^`JFhCi#8i3dwwSkh zO_1(eCrJ0D?Oskk3!d)pYEQ0;U=6vO{(n?5$+`-caSn@5`=ik}pM|2F)wHSdD4C1A zvF^vEbwBXimr-`DYiq!To0{@b^>6Lkzqqw2Gp;T?)E*LHkHt%1@|T{DM*5UqlE%bnU1`%0iQ&Cq937N&%S)yJ8RTLjYFsl6p72o}WW^ z7Z;9eT74Vn6IuyV@P;u#OvuxQ2OEQAhlmHy@xuAoCzepo{s&_-mqHdC5cXm1PjCtZ zb2+>`@B|**79OAlNAUussFn}9%eN$g zk92>!m7S|&6fC|_ZVcGx$>IPY>$-vY_3YU*;jdo{yw_3|N`utA%t9P&G&t8_Y>Xr% z7l9}33@>D_sJU)Ixg5PHfPwtN@o#^@QoXIM`91uDNOUq4$^pXgFuk12y_x#fMKh`& zD29=K45$Ofrb5Tfd1NbqoS)Ax`e@2f^Ot`Ybc{jdETV;Pq_K#4B;#t<@DUq=TGIbZL?jLpwMq`C+v1{j4a z8EfFARJ4e|x`D?5Ya-$5lgWiZ5ipSe%N&3Rd+TDrsXu-8Ld%PotRW@}rcEQ+=s7{1 z3vN!gn}j9j7y87d9(}CQ57TuXUjSe;4-Jv<58c5!ZxR)MqvV+=zms)gZg3$JHnP;s z_E>kfwG(x%60@aOlbtCTAIT!EU0;M^Mf)D3Rb+1C3yN>J&(sckC$ZnYo9sCKHX7@8_0yk{HG7cKCfTR@$<#g4UO0lN$k@CTW&lQAkG ze<~PQdf>%UoXllTtc*<>5@NRU%`m4>^&fxe{q*$d-+y|_^3eOo(|`Q@^AA5h{dqn2 zH#{itWZk^Nu=1Q<{^+kidHUq1AD{MqfLa^a&_C4Q-cPLe=)nMsX4*adU1u76o(0hWxYuk-e|w(wb-i6k7nLS~bRvAf+8(t^&|Ow(waD`v5>P z-$)E3v6Ix(s4^Jo?%s!1JwHH3RLbw^dcs6Fl+FdIKsd$`P;EU>EdbE;S$BOsf8Cmh z!H|1hVC1loN*x-8Gv%HrOk8+uV+lK;WpIKSBhp%B#SIcNi`#cn5Zif5jkfZOqpeK2 zrL8#UEVbCm-6Vo!Yq5_0I}B8w`A#L*jn&76lP|^4gdmwCTVGfG2DJF;Ckl+ul0i2} zHU+Ho`KB>@jGj%6OfW*(9rNCmmIsNiCjGbm8L7J37(s4ilTBPmxkuu@KrtsX7kt4bt6Qln}Fo;QM z5D5)p5{zIFn70H`cAi|YbQ7p6-tdyGtrTycTNrOclEzmtu2eekHj74ae|`%qdY{XL zMDR9`;;9kcY^7ids@K%X4luOD67th2`O8&0=L(&g!Eg(0*Xin=G!~MZM{FShKhayRZuVa-K0+zvuX2^^e^z&JL#@j#rHc~BjTBAAhDz8dH|W0DC}zs|+G+UG+)opt zwKqLe&u|W{N%aSDc#B?bSDnMTihxJsx5W8oW>^+sO3xdVlrK3UR8>vL!`j!7AXB7g z6Q1dlRI|LCAhS$Yu)Ln7QZ0dn7;UMgXvCF?w+1VqxKqOA(<9pQf1Y)-K#Vqvde8noDF>;iyQkyl~QjI@gsv7%x{W zmO{!VWs)u9eaQyKuoTXV!92j#I^PgMvO#xQMsl(;6iFRE5IqaC0y*mLAtS1c%=lq< z&`7yP>1pG73y?7h)$D*;IB|$zaIV(U)@HsThXB^J9rURms3oN9FEu5$4a!{o}m5~0~^dh;e^SX`O#)LgVDf0BSi3o zwp-@Zdd>k>PSv8~d|LD@xxWW|NW#ZiohYCDRTv>C2sxCy0t%g}XJ1~Ib%jBe8=;3Y z;{WXmki9AURt|LDnf*^i8KQLEVZX) zn-Mc>B#dk}9cG46ha+Qlo0u(NyxJBJQQX&rjZ67_>un26-Y+cdyr)WC6e!|EAaw(W zmJ-D?dA(4iEcl<`3+(a{yjacX5EVv;XGJQgu#mLzI>H)z#J-~nqHy00^35JmB22C* zXX0Jvf4?|Iu1vXhfo zvkK1MpGztWQJmMmpZrY*M-71R=2hE}wKEqne^S!?heo0_jGch2Mn@|8@O^a{MxVd8 zF5bz1X#M{EB2z*_mO-YIm=qw%*ng^um(c5r$8D#EYa zbqXCkh=LD@f;Zgpo_<(`35{1^LKX{(#$&I{fZo($^`8z_|8Qm9IwIi?k#LF}B4HSx z(GH6S2)SY@*YC|NzoisbLn!cpJ3$ABe@=dWcLKi?l_;`;#R<*ggf)@e4wU*}Us#l) zzatF~B{#EY?CilA`+_s}RuS!&|Ik#uwZT&4;_ekMm!OWPe+qS9EYt}^ok&CI?zFTA zyt5%-*6F!~SXg4`%T0?TS29&E9v64M+a9(QJsMaJb_l%iQ$^gDl8XI;G8&!~f0aYj z0hYLg@m_4X$|=d%9Dk_7@l3TMQ-?cIMe>!ek?tWgRcjks7U#r^$ z3}1KhE*GwSRkq$fsia@&kJiikdyGzk z7q`^)iF`Prha35T_a!lZtp( zo+1^ytObA*|b${Pw zrOZFQ@4K+K*anrJ%=8*v;&qseZ&9uzOjKJ0@uWrmMR|*c{=#QE)`!Mt<&&kKBOXsZ zk8kGw_hPf>Z}g=9)l`u7f5YbEv>(eLQ2W|XZYOImA?cNiBvqD7fAs{R%$91W7Ybz%FHn) zY^cj(Crz~&@KR8Fiixt)jX7`}N-IUXoqyjg$G3yDP*=!q&NN1a+$LlL`a|K4#$y|{ zv81FG^Kchg;SWFl@Z{&-KYn=n1118*S6f@Xr}t`uc{c=FRv zKmOzApSwTf7fc+c>e%l7(k%Wj-+1!V(;t8Q;pyLh`gz04x3+##K7JfNIVyxou3ALj zlGUAMB5aTOf0Sd2{*efuvWXzGtYFu$w1IyCpAYXAY$kN-Wjqlww4eI9H)B&+ecn+1 z8RH+ks$*X#qWwgVWLgMs@hxc>_VJ}@IU`E9PYn)b9TD@{9tdmf4X-}KZgJFe?M*Zsq+2x-tT+6^5bo_^5O2@ zZ~F5|<@3?;?%uKfe1$3GZUAL$PlQj{K9sKR+LBqVugkw39hA>5scrq(W=A622NB{@ z^!KcJ$`g5&ZZ#uG`+Q&3y=X7kUI#{X5?%@T^=|v%Z0{tz!QbjW)o>3Vie_Oy!2sy6 z)D_(&f8UgAOoM_sP^^0AN5Jdrt1N&Vc90x)I?1G_%#O{a*p3Se|Jc~-&PoVU;p;;K zcN^Ml-L+YJ(Jpmo=TWKQ`_vAV0kOtDs9{cIp>?(>6&7*C(w1f-DJl{2R9<@{Sao{d_s~#~FStf7Y&(c^)D_U&Q)E6rpX*C# ze=Y*PaGHAXG?Y9GrEho9(KTt2^H_Rd!kBz7D4%%gIUmHENswGHOwQpXVor*Ag^5sB$C9z4d_il3$CbW+Sfz#OET@x}&5^-zXo!0{jKtIz&e1;_TC8C87C zB#P%bA=+-wNupG`zed%mUDD#%hBvI3Jk0FjZ_B4gRK<6xeZ(pPX`f9OTnH+M3K@IKwtq{v`l9nS*A@m#ZTg6>p+;`3T+ zJioKo_~*I&^9ujGRy#9%GCMMSr(OCLHLxw%ZmqsR=9&0r4l0BB=~-#EpWu9KJ{g#g z<@?4ki#MZ~B!$PHo<9BI={hn&`O6qE1?bP7mrDf`ev7|(O4|gb_9yt&MMVvg?HIR7 zob8#6%%OUcP|k668qPa@H!`d zovVxTO0`XaS<{C}(}(M(4}au9EoV9V-DhX{H(Iqo-YLwNXO9p>Fg$ip{FF#BN%1h9 z5-&BFH8uF&+Lo(z_Qet~OCwY+rY7G-c?9bYQIn2K^O>CkXMX#}JS#Z*+l zkmbYj)wlX?9dvPPTb?;Rt9DAazw`WmLb0`)_Di_K9t0)MK_9+~epE{!krD^{ARS~@ zmVTA!Ko$?uQb%+ipoY>MA21P0;D(#1lrJ*TE-NTW2B(`Fjjgap`N|HtCVWt`0~aVd z16?P-sX^*<@|L-@S|86(JM%5MNhD-y8B>|{EJoBw$<$qS7aaqqp?Z{U%a!I~R)OIVRP=eu zk8tsp0>>mvDs^vKZr+8=0WOPwIoQ3(6d9FvO_KHImhDz5crgQOuCI7Zspdo88ie2)HPf!{m_^qNFX7^($al*a;ibDb&sork621+v3*mTQ1z8csAU*LXT=?Y)<<$@w*b(Z2@JR9buZic;-tKp%T}Tyq|bZ1tT^ zgkXvvZ*+gZHluW%m;z~kB$IbcjHMGT%9pgGms3lOostU^Kw9r_;^eV5|;ki~-otd7ykl!C0PTlF5hIP>B#aIoDVT1UlIg z9>Q9%FAq<8DYlOi@Mr~~x3%SY`Z{s6WagMN2z?(`f-*ZDf|sm+$NnGkVkK{ zo=M-wWPLq$Q&u5O$mG=kHPYFpvxeQ7XREJu8zN zb~;>NpBgIqXnLoABtTO<{l|vX02Ez=vQH33RepW_*W8<)_x|^~SaR}FReZI&PpV%$T|GPg&o>kJ+lqpFsE*y-5q)dG%%)k40(x0T04?h?f+D;E)YAE8Qbbmwv zl2_re(COwTn{K@jlRrN(1+$Ik<0F%GKOlb#SqM|M$&7Kvb@+d>tBn*VvAw;Nbj=HkG%`z052XU5tSEE=UY$ovVM=LH=O1b zI=s;!(Ks`GWxgR1n2JnV6fkc@0JKv@vV|6`j_EiIUaE6;4lrK$Di4KCc|gXouRedH zlH`bDS|a~g_i|a7ilJK&*)d&Dk>DxCV4_q96A23RNQ3mkaiL?#>zBGd-#r=-$yJ-d zF!|~s5lz%94ti454k(Afno?D2!1Nj4SWlfV({-9>D}HCI zNX}(70%gu~lbv;tQv6QQFg8V#QEEu%e^Wbhr3E^PLcq)wtajJ>U7u2p$V{-m=iVIE zyHO(YSj_pt`lf$$WG+|xiUQ(iUj%!HaoFGg$Uf5FC+vlM?!&gr*>j&wczu6-Ax?`E zVmRU7Xm!S`*Nb3Erpt4Wo zm_wsT!R*4&XsQ0>*!P?|&30uw%1%ma5_CL!jc0RhLn&+?^jmHj^7V|8+2pLJ?JQ2e ze~JCo#-0fxR(UbB;Z>!^5Vn7*R;^mhkMUTm?U=5{b%uhQVl|AQFyrxJK#rB9;YhIX z?{4r0+b+X<)Rh)%#YJ_2N18j=kyFZ>#ra0c^7B*%-?{K5bvDr(0r5Ky#6=Tbw%IG! zP$%q{3~H5ua2g0_o7GX&-5jqoV4RDZF;w6wjiNGyCR6%evnjn={~Jued(BIKZJC97 zZ@GoKzMVe-USXjwa}Z3aQpXModdVxbaHTgpL2bg%ls`wVY~AKa=5m`*lt{Vt2mGvE z43OdaroxB99xb1Ch{^m+%R2EI0uW)SzX2r1p0Yx+Me4kPV(k&GfR#~~9BCd4! z&1TM_4!+UJ+#H5zvqQ%SYIxy)YW7fxp*X|6FuazY=wB-4&x8GwQ)&Nv4ZE~8!2WB2 zsVtG9zLxgS*T(+&S}4cqOZ5Za7#HSi*E*_yV;Lp=ztq2qce1ShjqkNX>!tZ=-YVD3 zOXm^4x;}}Qr59MDa2vd|9^{w8@c+_zq?QY-{!9CbO{<%<%rRB*jH=9kFMQD3+TwxP zKb_oOWz$0%lDR{r!AhSsS1EFcsY`<}YY!>g6qcYf_RXyp&QouD(M$=aRzb9>6g!Ab>JUq6keyV_#VdSH>)_k$IoOu-c2W^H z=Q^)mAtBN)4HWbrtK1XlfUG};bZi4 z9&u-^IxN+Bhue974ZYFWUg0T$T~gF{SLG19-^w9Q(3DVU>bt8m2h8 z*&_#Ow)`D!a?eod+}!ldVRuwC8Db(3i++7{gvIGJfl(fRHSrj2`>VY7y9PDe(`j{q zQLc9@myC^z;xe&*2_+5&`qrI%Dqz1h6BozuW`homi-l(4{}D9Q>h-ce+PQn>8Z~;o zT?_Hrkd~vio$?%%+fo_&+`7vlNMEmKqFybVpsdc;Ps(Y|?&S?!CA_jydP)V#`=(e65n=1+un8T{QaeYL0ERC66Ry zx^3M>+Mm#Pzw%084{@%vW#?>qv}azB4Bo3HdRKEBf?DY9BI<)oE1A zE4s^9JoNGqObN*hg#o3?|LP79rp4(|C;3;ZPEs;|%aGz;F}#by1Z~RUjuZ#pS5M=g zZtuL7HiO?pXb-jjo4`b#NJzgusEq&CsEq%%R2l!RSs5pQe?|G_fU{RVJ6KhIfr2PM z;>n{XM(JUqVDtvcOTMYjw~B*%NWtkT+QZWr<-c zxgTI)iCWYN2iS{$3PGmMM3CsyqB_ewnAy|KCR6d`Yk~c=RDI8+?<) zM24Q@8fucv4*m+iNqslGGDQv1=x3#9^h%|sX!Ns6H2T4xG<}p>c&vp(>i+e4DT@

{jd!~0*Wbt^6-t6GyYkV^+$Ps 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 B^uhoD delta 31731 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

\ 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 696d5cd2e51185ad3e0467ef8711c065e6df8343..bde1fe17a8dddad0788b4040de413876f4a6add9 100644 GIT binary patch delta 56896 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�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�Fu7Q&&p3fJPNUA$PnZ6R6N2azW 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 delta 56896 zcmV(qK<~eX%m;?d2L~UE2ng8+y|D-G)qmP;BT1s@uTZFNHBka-(n~F*VIGy2>3VIK zeQniD-%;u4LL?}mO%ZAUvaOc*?=P0zGXYYrnwk6F=`M@NJtHF{BO_z6=XE08ikM}G z1iMX37&fsLwPzgqOpi}m1FiXC+Qc5ZS9CVsCmfTlH7u|R_*r0PUO!yMLl(1R6Mv0m zoFQ+xOd}F&KgCHD?WO)G%+Xzt@)f1PVSZ>3-@ac_zR(zzLZ!%Kh_!=!4@2#%IF-TG z8^hg}$XDKM)-tfJRh?butXm_VZW%WZ+= zYD&P28?Z>{SGQvn^IQ$B+mLIzzJI$L!3x2jXibW$sPWuTR6z9D%Zj$tAGxqLw~9Vb z(>1T{hm1IJ-8n_!{7!w&^e65%T;W(N;HqO)>2)JIpc+(jL#Qdj-r}99U>7V@; zxWEQ-r=FO@O83^A0ICXvaF3dR3rf*Ufbz(RCk~_3MqkCAaUmQArCG`vm4Av3o8%ZD zHZ^-V&QGTK!9lzho$x%{?n9;{A!scrl8hJOI*qK0Z-iR*O`HL3xIRduo+JHlSrxnm?9QH8HTDzGHqsne)#pxQi2iW#-1uhP*Z4-8b@f1@~_ zl#!z3F`eMHU+fwbCqwVJ1W}T>pIM9(0{6Wy=!e7yQ-W5!g^)X*D%7V`N3ZVUZ@~9LR<1%lJ^v zBem8#1RQGxaVWv-`F~Xj*oSvJ8e*^r>PoRCP^-fuYiO{X?5i7i;O&Jtv~!}Iew~$z zo6t3YW+-YK*8yx-q#8G2^4-X(ddO>udpOfHin<)Ea+&oe8IMMqNjVI)xfVXzF%Y`& z&W@D@n<0nMw=xmalO13~PCwhrNhge-pxun=Ncvx}LTwJ&LVs8ndrN6}zT4hcY)6jY zO60WoB1!2X;DX6S-Hb4`Lo^aHJwpnoQf)aLZxyuABz-nP(@as3a(JDs zRzRQ@@8DR?tF^t=%-F|PF~fx;c2Shq^}oA4xZ4$qa^=GnNg9MrYMT_#5*iWgSOCOO z{FvX6JsG9_O@DkuD8o3%T2+YAo@eV9Kuxn|enH##Eq;Y^VU;jC%Fw0w>Kj zi?9{qThz3d_xMSkJ~$o?ejFzG;N*b>ORKa_(F2BtknDM6!mCFGrEgtTTHb^{=@wNU zOB~!ZXMYeW0DfktO(N+Eotb+58li-;$t_a>yCTUDf@H{>O@QpBdwYQ;2uXgl1R~Ik zjDHlSWfmr~Pesv@7C=mM!^t@B_@9-80OQKwwi7ADaIMdK<+3-InRRbnHa${{%NIil zOJjus6gl3sB1h6zCr~CdWe&bx)bC)Rbb19MYk&Wcra781JO_5~?(RqHYy8OieE7Zb znH1^RF8y$1eLj9-e|~2-{rIu-Z5LNRpFMiGzpuWYJ|3HS-Vu^vfWO z;Qx6Iba1i1AF0Ks{$@FBt%qa}Skx~0n;67r54^{PBC)&o=$v@X)Ds#6Cp%D&CFHtVASpn4Chf603@N)(@| zE3$dr_MMk*zPW;7d@ifSi+o;IxCV}W3ft)^RqyYvzHDp{AGe|e3tWCs`D}Y6bAL%H z^Zi4}9TpMAJ*rTc5C1TPl9JmBZl%3~Rl@YXO$q1Ad3WB*O zJz(`LI}M?Y-CGt7fUmeb@72{jjUKSH^+7Q&*Y$%XAmAJ=K7V}p1^yde0jzr>+EWAx z(X-yutakxiTpE4Dx-A#QLOF8~Pk)8DJef5z2@}IH51|TU3d`6?zENM4pI?_5>fw>5 zM^M%#<-g%&M0t%@_nDohrWsmWt!^)tRSibsD|#wSBOZ1I=z}NIYlL<5?0>!ZeCqfO zmQ659>(ybawCEXB@BO@fY8mN zV(y}0lVKn)iMx^(MYhMGPcB6JX3sbdu~z67DD>c>LaCsO_Mg{9^M9s3NAZI{OVjsM zp%>`xu25`|9)?pGOUaASpN1B36qlI@A9w;7V#g;CSI)4!)NPnFQ(!KJOg0&#B-Met z)dk*A^tEB8SVC(N`WS7%<$z^KX$f)3^Qi>j@M6tD%C;u{Gy*52oJ=CtOSW&iu6$CI8R*?+vu7ezLpXIxvJPf2f3w9>lutO$UH#vfH}lRi?WmN_o3SMBPL zti^Jf=YKIZ?m$#ys;)e^d~oCK zlUKgu(Fu?N*zJ9a85~DOe*&{F5ux57&h>M3t6VJP4bxo0zO0LHEoMget?z#s_=;C) z{?)Y$=)%Ri3;6W!wOXsJ0je!C zLMOO00@-{XKTClSI4wK=4dH5zSh$yBU>Yf})ZIZNENF?HPDoQNH*`@%$fVFPrUeW{ z%~JtNhi=;h7S<{+6KTvFoD;b+@s`0@P4-sTmyyXRUVkXePi-0x;Hp%j)ZW}OIciVh zs!-b@Ebz();Moz5NMo=me6SrU3KdPYo`J_9rYm)@gmFa30yt)iMQ%G&=uUu-AD^_g zxcw@H9F_ITW!BIKPOauB>&vmQj!jU*98XGFEYhRzbdSoASPJw}#G$=t0kE*6@&;ki z8LRg+|9?W_lEv#1uKd5CQ+OM^EtPNOb!al)Y+S#WLPgD9{Jw(>}O^`}U!96}1Y0_=K@V9XZ zrxHG?^@(Gtt#L3wI9-j6f+7BDfC^fc%G?eFjej%JKG`ko?&L<~Q0<6utgwE)7P%O= zx9-~&R3NqhW8ro$C~oT!LAY(u<#swMaRyIU{{2q8XS7IVxoH;pCQaIB@2;kH_)+;Y zcHFnxkK@7kAdml?Pwj4{{wGv8Dzy?R=l_C2Pj48zcX=?5|LhHV`v5e&sMR*0^@CMo zd4EHOTh#?@0DvUo) zzY)MW$rDZc1;-d^Cc3>1D-3jNE1^@x;cLRXCbW~ubFBgJ_JDehjme9m7AKGN174e` zhNl~F<=>*hZc0aqW=V%kHu*6@J_p+L)qn8T%Xnan(>VopUf2HiUB<5%f@_!7X zCqX}fT~|+fNr8`g28BN^PNoGv=otfm#&}U;^a?MUD@apcqt?B~Vui2gp7Rs=)F;C3 zx_wW0VI>GeM&R{4KfaF*ni`twU&a82aZGZ=8Xa~qSP==9#ovTTmBs%Gyfqze`-PH5 z`I+`uVXFaWcwS+nA-x-zs`g{=9e*=A=r^;7%SDq2I2QgHC%3pz6ILs6+6h`2eK06X zKe!p`@!#O;LL0;hl54S2K55yR6>K{M{dZk#OKaNX$?e(o8Ib-OWpi^>c3jatXKxIE zF%PehAVoi>=fZ?3DU3}pZRnDY2~)=AIxVaS>C1i%cWu|Y$sq7LG(4fPD1QNsABti1 z*LcN-tv6&prU*&A)0kyK2y8x3i(*l7tL~sV-K-|fCb>0%GTOw$1&epzv9MRg5f!vQ z-*#VqgLi)a((FedAmKop6jk3@shE3J%~{XKz8SV$rFXbKhA(&Cm5uupl9C!PXFCW! z?8<^xG9@si5R*XJ6o~A^E0n9-%^U!ZO@%Ipnd;y+x%Z7&G$(wFTx3g>(WT+5rst`1^ zlha+8JZi>0`5iqh+JZH6K*;4zUA!WZD^fQ}9aq4Wte!UV=C%Tc#D8ZT9qHcj>I8*% zO0{%1UU4sYEQxGMfm^s!pJ$xbEf{tju5bdRk2G4t5ZQ9hni^cr1g3#iw~k|6he^LB z3#f!~Ik8T0LU4!J1URtJX4ZQoS*6WWSYaL-37R9jFoqiugo=g8UVej8<;2FVt?YH) zy|2v`&XsK5etu{i=|JQT~MWL ziKihFcFGx+4}3fp>+=_RJ?CSHjTLk9!dz=#7w@?gbq`#k zS!UBN`XpT`sFp9(xNG$w#qWF6)(yAI2);H_%%{+8R+-yplYfxG(Cr$ny+}}^Sk6)6 za92vz*aG_9U0=Kf`W6b@W7IY`(V{syV$|DZpHAPiVCt}L%B#Styb?Y<;)$h3@l|7X z`xNi5=2X1V`_b%!$lyQsNd}3BR(&9bg9k;*zT6h~t?^wGmPE?etK5Jx-2002^*d*) z`COShQco9-U0&?Q&X(C*ST>lz&TJI9^MFh3UX9#Bz(pE_Pq+ zq!W{r%rVT-3>B99!Ow4A7AP=CRe7Oe^=w8?2VhsrRry)^Ewvb!XW#HZZnv~;g<^L@ zw_=oK4u7E%4iXbibD!w#yy zrlrjg0Vn362HZ7eqr5e54!!L(M5{vKO{BZ;uBOc<%(fj&xP;`bZpDScKzE1OQtRST zHwK`|dAAEq;gi-)cfmnziEzkPR%egwz8&)>^tsIo_K=PJ`|U~$)3h2Du-Q(vLz=VG-I zB3r$eS_%&>y%RGKn+!VW267ueakj>N8yKs?v8c^)Jm7aF^ za)1AOe}H%t^x!V@c7aN8B$}k$b4(pW5+gD}1AorXVViZ0C9!H;<@v|06|70`)`wMP zhfYEsW?c9(36=h|yVt^?UCOJCF?6CjOfiyB)zA<{`M^jO$uM2{_`7)^ilJmD)akQt zZ)Jct3jJoX1@=_#%@5e85zo#VLEJO_c7K}_U|EOnFk41@}; zd|*nEb2hbXrTC;r#ZAAxq~J?M*?8g?8Zbseu7TaFi%3ymqhb+?->wB*WhERzi;hqAfsphhGQoIoQC<+VlAgeI98^y}Be6FFw4c&_AAcXq z-&SOK!~-aXz_kYT2GS|;w;GJqE3cIS4$o~fovWUwY3!14lNPMWuF`0}D(jrvjl%X= z+*xRpT#d)sIwakM?_gO_{*Z%Zo1eOmZz7rA%e4Ua_(Tcgi(Ua)agHWfZ$Gc!2?wcU z#GD@&C;R)2yb`Jh{NX>!V%?8=QGdMQ_VCI(4Y;+kE-!8JOiwUr8-R)D#V&nW#+ywd z+*7<oPGMtsN?OslO;MTAbr>&!b4zC(EZU$KHR* zj?uLEggxEMxb|r@z__~!`ugt5XE#HXr9*p#i>m0PJCv1f#&;{t#<9DVEtXYwnTPXK zLd#^21gz~DkVSD`sXKY94D4eXy3>JZ2_hRa@q{R%u6L@dH2qq=FNYbn;! zQi?*0Tm%f7{Y$o|I!I|$&_*8@VHS;|NfBdn33`Rae7>PzfmtLo30i$SGY!Ur_Vorz!ZExIsDC&(-?O#Mi~ zpZ65BPI@EwKe1wP$H zJAcmwtYnlg|8#Z@+*ExTj1SdD4RbfPu87GYLV)LQ(?WGe;%u{kL}KPp`9N%^K&|-h zPD)8aH&P3_#>GZxrtK1c$!ZVviYG$XE1*8ILv8ZOyKn;cI20;;wOYzhHidg2qLN2a zrTqd{DQSa$oU9E4k_sIp48|BZq#w|xNq>~TAKENMEgHjpv}nCTNC2av(FWMsR=?k& zKmgErUhn4rpNj6Nt-=u+j5pKZo0|D#vsXZGRg{zPCE;;lWxsnTh_hR zL4)wTV+nfXjNie)q@>3b+Jp+2%bm&CVdOH(lP%cZU$!ne`a0Zg#j#}jg1a$kIe*@R zAFI~##ApQfP{E0%>qg-W@)B;$t9-fyVlN&n)nEoo(kq}~BlGJD_0B}B5ulvq$J{H= z$)X0u%N2@JZb3>-9zKR+M5;TvML1cMQIk~pMg)spkd#)z4h}Le+nw2CrdH%`F7nH~ zwX86~!wxn{UCmnyLY|=dCC4S24T=-+}OHW!&hJI18#fbc8=1sJT+xmxg zU%Y&E`0MMV)1RNe{pG{UBT*|#%sFXnFC$!Ns<9# z<&g`}L2IjWeyX#EXE%S#Z~9(!XVGSM3AU|L-6!_Y`IEMQtMbfBritER(AWUj4T{id z;-z$ScmI0IYG+5#C2Ad%6MuF1-5%`V@;ox?2uE#vL5on+BJwhor&=eM?hEuxqHh9J ztD2`0Et3{RGJ}n1MB4qJ5w2a4Z1UsKu5qh$4fEikr}C=-xjH6K$7vMZC+LtmYNU3~ z4_9BNa5iCC)K(E1POuB5`UOXzCpDHpYV9X_32;8uWi`1fNr!v-uYUnCfvDJr1C+Wm z;y8Ldf&qy%`mL0%vMU|LOlaxR)r6_R&gFtyH=5`2!g1+!h?$q`eN(JIh61eXk}$)M zUTAgl@+=N%sfINCPDb$3uZ3HhmIbLjXx{pk?F(45I!kRW1L?N4Pg1ofX4{8<(Kpa- zM-?uyQ8eS$<0n`(%75n}SRvHbQNnEI(TF`GH`T|-@COxjFpZon!(UR|Sv92B0)GwV zBFx>&eE2&vaRb~{>av__<<90BvPty_1M>{v8 zpc=kc8g#NCo`j^UIW2*VIHH&c+*s}J=X+_T?BH7pk}JI3qJJo{-Cw@GZnusXamCpe zoG~>cU3nDtLXS(&%EI*p7CtJPmCXdAT1ap$;cU5fS2AE8Pj-viw@#nzSMh>kypq#s z>1~_6o+ru^Fh`MCuoK{b=LQ`O8frt8f<`+CT6Q&g6;D0ks6y;g z$^ub~@G0ORffm~FEI?^!A?2k`4fF7jZ_mcrs1lt4v42@mID(}gj3e#TGmO@@WzwvT z1YFv+qJ$l_TY{)`|v!b4ChD<);y9M>2& z-KKyw3A6UvF=>Clg#QmA=dvGDD3!yeKZ=J<`5Kuu^4o*vY2nZ-!r8P_+z)vzkdxn? zDNqUlD1YSrPJ$)u0nhYCXZh1I=qVbzrQ>PwG(Q-7aAW}Yn?XSi@=gdmbt`yc5fIqq zm}`>TzWofO@jdX(c;l3ey?Rt|=U&Ga(_O~wWl&xL(zF(j3K}@BKfeDaz#J6+*Mg0}K2pNaFh7D1n}HXpE#B0&Qh!Igt`XX+rMu0&H(zUobQhN_UQA#FUD#)g zGnSKXmuXP?EUWCxVEf$+invk7CH|f-!~WvVd~G~#i4F{rSra}c2t zw7SKr#}J2Q%+s9sg1bBMBw{>002h`_$Q+;>5WU>y znz-KY-@yLrJ8zUoUMC91iH_I1>EshlN2K<{5S?S}MTSY2a6f9{fiEl(Xn!FdRayAc zq9x?0;~c`_866jklPDbgBtLG3kefCej(w?Cz1=sDiNEw)k_Z=>Rm@#{Px$cZ{5iI5 zqV;huqsIu3ElycKDoQS$sOCc&DQVoG#$(y?I`+$less|^SCa=1K7al^{QPKGR_6~M zjz*&gL^LA&7caJJ=K}Jn$bUcoRDMAM7>#-(R@ldXHNw}y3P}N@aq=)sE>fSv`U+O% zJ#sG4^_Mrr;(x<`y~{jDSG}d6D)YKN0;-=z&f7$f9w&P8*{a76Ry|=+K<@@31f}?j zph@#pZXNrV*8*>>rL`YT@wH24d$1 z0OY<)hLvxeXRl?s#z(fxOMErT>fCb;0sv7jXT)8^x9WLSzV*S^$CKD}kN~v?LbJbj%V?BJp z$SEoS1yteUXBIHjL+KA4?G3Ki+8?Y1`(CiI@syVFGXwhj(MZJf1>$hE$^-AO*a)my zBEN5P)L9>7utu@9c!r)|cH04);OnOmvm)3fbDVXGaZiEGD#KhU;K>m3+&jB_==~^RJ$Iwj7sX_ zB~^$hEg)%Prb8Rj3`WV=9yG?dgxZJMm@q?;D;pTGbsvYRR04 z4|=&=<|GrQ6A)VJM_CkG;nGRGEL`uUI#$9omp9eTJ%3eL_*neo4~6#AKx%=YiVAI5 zy3~vx%TKX?pNvKxX}^cMN~_9CYso)K6U8TJwIE--_rH)@NR?L2>Lk8xC(;AFE?00C zZN9-ao=b;gxBiJ}o-Ka3bPtT}6ij#J9$5r>DhTHzP$AMcLCCvl&bQU#uqN9_6i@~H zgoOgVhkq->rNxM-otUNg@XCSzdE8FB)d>{RP( zGvwv69si(W^gy^hy49Z21k)p=-5XB{=2oa-{a~nJ;cv;T5GN&_AEDQ<%{R*9_fJ{K zfud*y>$xu7l&d$_{hD+5)&tcCU`(Y|tGv@Vz<(Llz|-Z5DYBEi(gRp?oEiy?m=I03 zXSO(B4Ej+FZF_rqu?^B8@uLHV-7Wjb6M*D>V-?Q7TxIKp;pT6!xUNX3JQ*)Gu_)WDCq2D+6O3zb6|c#I6tsPPMJ}_#7YoUYB>*k2Ap|cdX*&*)oPV$DHS61uBP#m$9>~G>?%lA1%Kp*lL4x(K z!jD~V0$*zl^0TGGJkEe@HCk%xRJ@eK$GykJ3FdsIbU4&lGTb65T}7(%3rvIs-wl9_l+6B7OFtuE~&f>Fx}{X}vw@JsMAQ^#svql?}St zYf*<8BGk^}$U1KME^W^>OFtqb$Z2P7PdLsE7~Y7y`&7Y0sYQ+k z)ffOMNJD%lBQ!DfU<9}#4PO0Nr<-Iv(u!&y9Ia~=V%BU!zMLb0({ECew#I%^8mPj% zxU+?yhy7ULBE(30)F9l<;l;D2 zA_AeN-NR`&LujiJ|6%7V?-zZ*`@2Q6YRYMihgP0~a^h4awBWvsE)B+1G({&#MN|D6F8=Y;LGqM@^DjLC!D|R?+^0f zV)5nfPWpbyNIcGC?H8mBX{!!3mKy<&nEV%7w@7+sjL;ue7=kD}I7pkR@fgrvP(VWS z?J0(#mf^n*Rz1xXmVbm7T4|ZN_tHtrk#|&LX?5^PUKYb7qQnd?1AV`^$6D$;iJ^10 z`w*!3J;p%gw+_O-yPLgJm_(;-(W^TM;Vs6Ty+02Ng$L4YS$-88HEGOSs@gU6G3;-z zy(TslV*WI=#eT?KA)7DQ$$rFw#z=Vq+EQG~4WWV&4OmKxp??m_16fzAaFH9u=Rk^n zLIE-IT&se@EX{F&(Wwl(tSHm=QgvE#FolBtXxj@IKq^Guk{Yh&@A3+zyZutMyp9vP z)A=RpWG#%WhC*J!k!6kGpq6=EyXqQ(fAIS-}7DO#mZrrl$Q z%c7nq^?#ABo`24hMQW&yPBCWHMY?wpCl|A}S=noZ^EnVpHOS}_R%K8nngmMS)9$9Y z?m;G+D!r!Ml|QJY?S(p(^uf-1RD~>E{*vblV1Fe})#griO9f1M;h-CAqxr?t(QNAh zQcU^<93xwg;-q*slILD$doi*myMhwt0Z3iGQ&OE)ShHaEK>)n&Te^r0~dR zET%lgw4XB11=^qE9zF5kXY&BMMz6G?ttI#Ru@@4V0^`=s473FXvfw=QfJBV2)t*`EscC5+R%^l{v3cR z%Ln+u&BS{BRq3kfNrRp&Wv@#(bAbAg`v|vTsn-@z)+&@Lmf6A%gY9T@m4AshehXbI z?YcQ5gk(VLh$9;K!PqEnhrdH@%HIlK84d(+;eUf%ulIxr_tlQ-ka_bj<#FE}HJK|a zkL3}4zUD96+kuhO*HI&rou7Ym5KqZheC%0(@?D2w^CFoT@gjxY7r$yn5*ZnRcJ+p zxiIruEEs7UcMBw#eJs(8`$fxQNbm4^Pk(x-ZSJ=Fxl{RIj6EC@-JG2uGJidK^I8n9 zEe=l4l2w?!Y&_46MyB%IXrv`QV-d)cqhG;f_g2F2MhGh4ZftfBD^{k#93`y)_|Mqd zWD+cxlwlvKLQleUlFHS@vPqWA?U$``R~Q9DE0CsW}gFvkkBf!m$-7X9$0c8_(Sy7 z`oG`O=`!&u3{{W#m~V`MMQwlRAbSUia!vyiuGE?n)AnE2p${^ z=K{=d{n4Z0R$GT7vPa~B+Uu$9I5ivU!6m)HM*|@J#(8W;Qg@E~!>cQ15r0xIm*Tp40fxf~3eK7fWQuOC2u{9W*>1*KO5hxL_mJPpIf8|KNn>exGh+0t-UzMvk z>CVTeEb;tozF)5Vw||0WYg0ncVl;{qo~N2`7nS;8?xV0{gwVAmv92w=k88*MrAUSA z*RnXb)CAiuGPihNk*>HLAxk*wr4jkiy64Eg#T7?y_w*?pJ&W{k(ipRLxBr zlVk8}P{kOjgAnwVBM!}FdX-gm{%Tcb4F&zkss^?ZoMrfoYvtwZ1?7zK>2^I>!og>6 zC{kyDRT;yd^$dvJwdE9KO^T1#Ys1fyf&cw{u#6u71b^1?Mxe_rfnm}x(#*tPP48hY zlX-%@P`k6jI0_&`Vh-fWpELc_D!XBYPYH8x$C+|R3pJFdGLsOb$1>uIM4(oOp|}?S zHTT9&yVQ=rJDi)u4^kMgcZ5$K)Yx_zglr96lqEaN1rkuGcI|g>sN9(?1ZU=r1@`-r zTG(`o6MxJwY6~gn@CdzpM|SA0jE3~~4G^|~DyP4JRp}^+{tx-(Aih>Rwu?oZ=7zRf z7EYvi3_Z;vdrb{{FN#GEc6kqAgU3cw_SgY>&w12i;0y#jAIQJd=J2AqT=izrW^=Or zHsf3d`q5{AUA4r(mC3EOdG*rP7a1^tLf=50pnpp2Y#*AAM78yG^Xr~9+ut+&cP;yc zv%?w=okC=$1>ryj!tFFA)TLA|KjKX$*|G_}O=>$!HcS~jx%whaFb((Y;z<-Ug#dgK zML|~*kL#d^d2MA%PWEZ}Cg?z^>5Y2OZ0|exZ}15Ism{+bG5{PU!^aqj27}pfKvmI* zet%dr9=5ni^=8SRC$XHk^6#)wZ?-**lugeS3xI#K%1;s_5954_8}gRrp3HY>aW4jZ2n(5_jhz6X?|#Bh72rFLiu4NF|Iwx8nw!oA*x zR>-Ko#FE%KnrZ|`sPSb>Q^0Ums-+#CmVbSuHsASmsD;E!>4gE@Sx!wTP)sWi9M?@T z|9ErKSqP`!z`f-Rbz_REZU*IYfVUaHmO%Q%b{H^h6C=bs7wiJTJ*zvA*`;R?y z=^n5*PELz;(R|SFHk^PW7r6OcQo<^${RFcL-Ra@d@>g1Z|G|l-EN+ksQ<^R2b?}6F z#t(7^0pIB;vJ9wk%sb<8l7IfS;p^1UfRWa>VTbcg@2X8jA##C zhv)6Lmr?eZ%|?w+X$7~UCzt_4(vSV-DG07Gjaw`k9MK9o#uEe1f&(pM|R*= zMv+qc-Iq3Nw;6!2Bq06Rg=n$a#G6i;pVX<>21^$PlEBtUYWPoTH~>At=&7MG$%WAb zAWkl%@~%^MovKL97jcrM&405{DN`t})!^0A@9+0(6Ng18G$!w}^5A090MA|_OrE9I z^6Hw3BxCS)O{J6o#;TUo@kGS6WBnw3;Jy%UMbc<=S<8(ph9aAmi?YAJehNGuirrQM zIu^Bk_GmPcyTB#Zut=Hq18-4nrFd*Lmab^}00k>NwqJeF#L)5G-GBPocog4eaB+oN zvpTINd;D=f2-(}f*U+jrC38-2l8QYT9Xp@*Ka_t&d3?J{#-QZBA0Uw0V02q8U^E0ZEW$U(T_|qToiLN zN@jN7wp?Lb6x&|e&!vMA@0nIS1gUGCeTF1>>r?b{b1%CZA&I!J=vh?T-M#X5zr7(Z z$>Ik5-DAVc->5hK4nG4DLhXr@o%9(a9jLtI;ppm1yfIxHI&G2bI-T$PA=LehjB*{~ z+-H_JH#C3ru&s*G0L#b8Y0$}bF}iePXtn^j(OR8d_sK^5x+FiYPHtHNo?O+@s(AJ> zmIP_L>`0>Dt|)tv4KNf-C| zza576wRMJG7Ls0lQGUiel;D$4c6oA=pjh{VTO&2)UN1c;)1k{sho*j{0+@Zf*evf!$O+V27M)<8eM2rs-pz?^~@+2U~a ztCo+J#KI69tUO79e)oO|c&sMSYLB$nz@b*i`Rup`)^ay0YeZpsUa%#jQcjAuoP|fOpEfySD2#X{=Y9;B>Tw^aZIpS$c8~=_K z`(E|qV@f(fT??ozpN`zwS|i(|B3g1`=1N#+ zD4&J_H<-+=d$G~2TxzvF+ZeqYavguc+E&rQR0gy?}p|sAsHr z8sV0+8@M;x8dL0sMU9uqU3e(?2YBLk$k;JyHum`2;8vZV^&dWbl=Qy;F6lkOkR)e# zwzolf^ytU4{K;l`jzY%vQZEiikGRxLTOrd;JC++f!GI`j%hyVA33|lC(;hKOFfr8m zk_?M%qPIpa;jxj8-$uT`6_tPg8o!Nv3w>0n7dlm!{r$M*qm1i2pte2aCRD>#hu5Tv zG7VB?yn$1k6zYN_rO2O7SUN8TX;&~f9NzGNBZR?&pg`1MUmy3p}#9!&+OCKG=Rn(dO#`}DQQ zKNa)*lsv8H-T>&UzFv!8*($3pPv;z1=M;`vIFu)b2#V!fvVCX3*XxgKboq_G+8B7V zXb?@rZ#^3?mK_@MT(7fFS;4+kbpx^4cX-YnLym;&Kx;%uf#=9a50+Vt9wwlAzBtW3 zXE$ECb%yQEa((VUjc(@VH@0d(=vLO@u7*f>SPYsCxn zg0DV;*thv27ODq$%GUjDk{u%V^ zs~w|X$>ISfuUD++tLsJXwv39+fPMoiR3nfC2W7B^{o{=65^Wz(tXOA6&WLxF7H|+Jn%cRQjh{Tjr7Ikd9SYK z#J>}CUjct`KU8xhMnb${K;0IX(EZ_cnJr+C@q@w&KGH~~f4H8{;Yg;e9PJd1yjO5k z0s^iYMJ9ph*i>Bw&QSxQg+xh9TLqsa7fT?=%fNV_^~rRyhhqj{3)zvq<-bC7WA3ly z*LN=tk6xbs{L9hH_y2zQdNR%*??iIpqwV4%Ty%e#YlT7*^E)KH;c188Rz{nog+K{X zw2Qwrx;5dfk5GGH(G_8`krvs?xI27cTaz>{NB|Sdwwy0s4y;?ObOVluX*hV#QiJzK z{QEC;8dvdNXAT~(c!Bv^Tn|PdZpfdS=Ax1;?V}|y>L-%cF=~GGg%X>E4{77Dvj@>W zPC9>$4l)Bh#BTL1EH(b5h%43>?k+vvdKkF?NIZ9MyR zOTh_ttWhE5-hE*x!Cjl-qRP(CfkN0;r`pVH>U_(MA(}m*(3r+H!9eF4_Z6}}xzEgf z6dbrO-kp=SaM3q%GzaJ(P9uC)mct%Dbmwb-RA=P&!@Mdb;65HLi52hF%ex0WxxcT0 zqk}(R14@BC9nfqU-Zy6p{NGfYM9Uh*`ePeupwQYx8~A5sUPD#D*=b9JU<2zy6m<8E z2P5>LMw|kJt{pdUYP+sZs1wn?Y;KEIQ=8fGqwh3e2#i8AiC7=Jzl-J_jTld@$?D91 zQJA`fTk9&9Y!#~tw$GUbZFsihOE;`l{8cN&&Fru;#rhLE%iFf;+j|lXSfq&V+uJ+3 z_jXl%+1quu?smaA*@201R_h_X78eE0IKGsn!|kfVsN-pBa~OpMqv(|9)OIxx15ba4 zJM|FD8nR=4hvlC0_7s}`+E_Up98|V{7UA0wU?kl3NT9#W&@o#g#d zL9sdMSIa$L4)T2t4OXZ-ehs&1v=ILV@SjuJQP6G?E!p>s=ra^=LImrZM&u^Re3(#1 zOY@H(Fc0q2_=JID50@g#J}iWfB)W*Q9l|m%;rdQ-<#f9tuQeQuLxcp8cxYOG$3A$N z7_Exc6h>|Qk=WIlA9A9^NcJdFBeE^AOfY>B7PDVcZTO=Hn|N-|%z@2}k_Y)Dm!_Vk zL6K-(nhK3Vq>ap>U;c6jRs>bSbPUl4;VoC?Fnr zlSorqEVj9a5LGe6?JZYSZ35&{~}pa9`(d}yUSlFM}I`Y&O@F9tw=I}Fu*K$^Fh zU_wI3=Igg>em@Lo^l$CP>0%w|p|gVr9dD$DK>j{Ju@*!gxplr;3TX+P)`EIM%UoDc zE%7$Nw_JHlOVuAWeyjc8^S)|tqpuS8OG^bYfmV|VTmvUlJfANnkyLkpGJPdBk4$Y% z$m!64!l=Ed{zQM>2+OX2?o(TQYM{0A{DXd*$CB0p1P>|p2P{uO3`nu3yqe8~e0#O} z0P`s3c^^F&?B&YK*<0z>&MJdac4NW;Lt7K#DJ+3IbpIK{s*$Ef|NTILJwHvJN_N+> z8GsaRKCfeE@}k^w*tvm7^t z);!SEd{qK>8&9wh>a@Vr3iLAGh+;T(U@cLxg?<4+MF*Q!M~Qy$sd=vQy~l(xPWM(k zwG@j<`1NNK51WgBd~Loag`E>y)zNRK!0W)CGT)OP=8vp|ZTc=u*;zYy_cPyD_4jm4 zk=}Tk{9mQ@NrST}X_#!b==*5|Z`Vs}I>E%l_+6UHI|?p@uxO;8>mNV<{?U&w15#!w zOd83TA;+v@p4RKtm4OutjPwv1yf6ZSMY?hSevO_!+o^1-U`QZ zkMi~P+A3`+4|Y~0#XGkr!8U&L;`#F*$FD;3~ z;g7|&z7V#57ai3ph9yROl^(hf7NRw=_0k9hc~LAqAGLI)u8N@+c=w8)BEn`mro@8n z??W;-}v~Qh`j3AyWM`LTd*HP`dSh zz_q6jx5k)kSlZg4SWY&9Y@yeZxS{h_2Y(P1Fx9qyBhvUI^A$^)$dnGGGm7YXfSEVsXIB#-3)O=mV<*QWaz!lF7sXV z8Mg^qJa&LuK8DT~MYbx>Pi`%1Zz_REG04u#`}SYw=!?RA0x^a82v7xv)+3U%eN{0_ z0#EB_rQmd;o|+F!F4ix2awnadgeIMzwE7Engb{}Wg*O!R5L47b( z3capT$CeTztszEN4s=-3Q@@x$z7#%XeU0(1Eo|x14xeoJFt>K5*3e=;oL+-BLYA?A zP2{;5&abNqhIV_uEu*x!lr~ZC9{`YIS>%hJaN#Mp6)tr<NR!r^15U z{0cV{Fir_ufPd|lv+&*8df_d!b?d2rYp)0Gt!7RJtPY}Hbg<1#XV=|KVSmtZVp;tU zZE4=afd_{c?-ZWHiSlalNNXlM`rdRb^gprl%n6xl_$|koxD872wvuaaJJmv4!Z7qb zCH-FZ_HcPF#sOC(X+*Gl^{-oGWD z!vZaqjrN|Se0s|?sLW!AiTn{q6QTFEhpXRvRvGIPk_(MTt(>dZvS6KfL->%y$t^@vLcuFzww~H_>|56e}+y$L(u=vBibK>VYJ+T zIC?oD+DM)2=QW%=f6Z6$Gd03PyLm%Yb|hyJKfg%F-NgZ_qt!uq!@`H5;4bwo)W`e&{{BXxv737j6~=X~)F&fdIo z-HOqNorFp#PSRDdF2)`%s*Y)p%J7@Ku3gtYYk;pIfi3^mjQ5;rAPG^-jK__exYAkRuGVyXc(2pgjs)&9o zDR9+bf4MNaEY|Fn&9cOU^z2JGy>M3uN;)ZZlV3SWD4%uLdj+?Zi*n^!2g=z-tZP)R zS2yk38ehEa0TL7y$qcqkkAV{26>1-E0e78!%00ZSuU9HUv+8_*KF_aQ#J+@r1uB_3 zd*&3iv)TX2S-$w`rVR>Ij__{PQOr{8iZY}!1Nn9pksdcu9vLAD+WnZ{{8W(77_3oW z6wBtI$<8K_PFEMI^Z}EPvNMc70d-t`b5oTZgEA4CN&obAaECt)DU-{c5_%$m3Kurp zL14?^^?^Xl0F3&7=pt+W3X60E1U5aU*Fs=lr4ZiuIamR5tRUeM4#W#oqvib1dHxap zEDK--PC6d_M0A@&Yel3>FmupKi`*TaRQPQc?puWxxH50sm1n z7a!>2Z}>mdS0a20WRYJpX-Ku+LIX>1$okCr5P7H>|2ZCiolJ5e+orHM!(tKh%pB|$ zQ7D2#>j!Hj)YufmsZiIMG~*?p3;=}(fWy(jF30J?!IYG$WrUR9Ke!BooqUqCyd_|X zwS2NLg}xyC{%Lhxd9gBbZ8d=r=$^APC(`p8dew|T&AGrbDuR)H_C$CNu|wannTJF? zcY|@gKATs6n7cZF0@T8}rI#)@dL$eVxZPqrEos*gs+L59an$KLudQOEVxYJ^j@fVC z=>@^+&^&uR#|}oOfRMRdysOC<-r;(I9pF*=JcG5iU&E^#6GYbXvqOjiuiaVIOl2R} z>b<<9v<&|fF7k4XimLNW1j;a5#(+FRI&$bTDM5OF(A?eSDoB@2#SMtQ-hEHiy0Ce;6nS2z57`cf6L|U0zr7{3Y_g69C*T2Js^SNOE?42D_^U@+f{K^K3oONp%bo z^#_@MG`TF<#Ez(^kd(@_?P0ktDjp2$>5JS1KnVvhs=Utga@j+r3YnFqFuNSi7F88* zr%samAu3HX85yjVmTWd1x0v*}jm}viI1k6;o4@5ZetgdGz360%4+usdWc}fSea#jF zJ2`@&itTzIK`l;J;o!S?P)&k88F^;S{vefqF{NWi`@ndU6{C2Gm?qNFUt9$fP)p_iXuVFHS{C;@-aeU5cq@Ku@`kiiTH!MD*h#ZOaS1A0+W()X+WtY4NDSl8K9(Z$5K);$FPFp+Qq9V zK4fbs22)Mp2Ty|pVPY2ao63_Uj7!r`0-=zEF&xE5c#qfDOK*>NXtS77VAH~u$RTBl zO^Yhu5gw-%a?ZH>?W#{7cr|x5b2W~4ZwMyC^vv$V$uc;yAW8pfrY*>Sry&FWs;n*@ z#}XYp_({i`3AI+}3xM^60muuC7OSq=YW|;WAM}=p1-QRuftvMYs1B=#qZI$`r@UHa zSFVgzKKxtVD!HP589Ss$HRpXr_?8LfEpA|!7jrX9^{HEZOAa7HKJG^5`-<#n$KtsA z0LpKL5U*7@eoBB_mabxd2FqUyc1$7e`i*i;kcvAn!8}b<2Jy^HWu1MhKC#lF<)6@= z20-+DRRDpmR_5SeR z=*KT_U%W&aG~Ary+%0-P7382(HVKTmuC9b74wPe&Yq?7SbsVU)^jnk_OVGs3f>Vi4yM^ z`xfBKFH!0C!O#VNY}R2u3^-()2gehg9up1q;2|djN=Ga67vH!Aq80KneTBP^Km0QG9nd!ZHG=b|KL?m%^uL@+e1Gp$axb zP6om(o2%@9reultMq`Qa?B^BwiPB{$LNu=o9x`%J8{SLy886@WBvy-hxNd1MgGZAF zno8{Q#_rJbP7Q2ViG+RID*t5kTYKrciF#XyKebMPJV*(OQt z+1IMo+DY9BR_}G!wVNDQxP|T<7bmG-8dBW`3$HC*y|8QAq@2kI3Uk`#VULR3#nIj>TC)N9xEBc_d6+Hr z&z4r@BV4%Ew9uqC^mya&A%Y*U?huj>F%MHUChI6lBe?wLizwN8CZv&yLGi`HFxn!~ z=*muiMFK;KQ~RYi#CS?5pPoX2Uno#1QhLe^a6oaAZz(SrUFCGe*}DlG?tDx%d}BD^ zjea0@bt2A}MlkgUL@y5{afFMP(Z6KC1pNr|t%<)xNtqP*(q5+*vTyv8tkMh78T^}6 z+NWO5V;jgZ)(2wnagv#(M2HYM*kpAerx7QA=MFf;fvQizWqScW0jKp-9w-pZIu&EC z2KCc(N~i|sah$B4(&!;&mGV5Y!RqOfzO%tHj+1Q+4m4D=!@sS(4Yas2i)xh3e~ zxrm#q0WmL>M>Yh4B@ObN&X$uJ5j*U;X@FKvo1w{C4K-(Vch}#(NA2x}p8KrUOg?LW z_xAKAj_*kdXof}S{+>1pkuC&3D)tX1zkr*@x<-f>Nh@R$VlorSQYH~EK22Y?{h3+g z-I_MRlra052yQcp2nXr-vzsv<266W$u#4rgJN@Z=Xk&*)5QrBxngD6ok;<)7F=Dvj zm9v@wF{uTxfru37>5AaUAunB#jSR6l_oc0R}kVuvMs#rtpAUDh&_sz_t)u)W4wd*u}?yhBcGxI8A8g*d7=zX+4Qx;lX@kRnF#x{B3Gm?I)S1JY*N5A)0fQ};DbE3anjlgN zZ4!3DHy=KBi!|L*5LMhh{zQU4d(w905ZKUKkVO|RaTywktDd;vYf+&*zRe7Af2+I< zt|9JVevQqfXgjE$!`#<1zg> z04_|7>*DyK%zH#X24>#l6W+lW$KUZUtjTViFOHw6%a>Q_8a0J;INL@rMLkV%-Q8Vb@CzxQB#Y~=?6j`5dHmw>zq-;wcVu|hIZhY}2jADG(mnUbhw) zvwb>QZH3E-%a0zQtA~4c=V@B&!m;pjZw=X95<6!7{=T%?5btTyQ?eK*TLG95cY|CD zNuGdw->}ly^0YIJMzwf@P~&@nt~=oG{{CnWGQ=JfP%*}TBs?NZ+Y}}I)i?!7qIXuW zKBUOG(DbV+lMdmG;!^R_K}va-R-!%o)2}4@L`|iy(d6TWP^Sq*#Q*SJSgw*NriI^5Jsm0~><$tE*(O4u&`XX3+9<}W1 z-(beq6*_ExUo6yKf_r~A6&XhrqKf^_I#3nJ5xNN>w);uWTv zUXJ%hovlb)HMgC=C;ng7CX)GbNwREuMSNUfxc#J+pGwG?(QtoG|kEA!zQV@Fa)tGPGj3( zBwR?Er2zptLsc39%|p0AFY+%(s3@Qlc!F7 zQC_bWKViTQKol_+xL;+!(^Z2(ve(a_rB!TS8M80Ebi%oasP&&xlCO4HOpG` z4EL#ja_)UfjE1V)Bx|6tPpfI{P1KwE!T2P}(csOUT8b9!32c(L)q6TJMDzCHAP5fY z)nH*U>s+V|RAyBQexnO*T^MEEm@`-YEFH!6HfUXR01r9W?a2r(^N&9Xq!uEjmURxS z@&G{OE*Gys=B*N3=#6|H_Z9@n0YM~%wbwC!gLO;*b4;m{J+5hZT!lBTP1%Yqd7?t= zC|J~2EA-t`B_m}i=)e%4+S;&U+gdi3S*q7-lZ?ZCVk`n{oA^d%Eqixrp^dR0+!p_{ z%{WtRI)AIuu<|wfx_cv_?VE+^gVI?pnV#U*pi``SYHr_CV$XO*UrC!x3v63pgqEv+ z#?I*HQn>D%0kK>zCtU~y|3#b6#{Gd{3EUcz*WJT8qu@>CTS27t$%4#A3Rk_S!L^+> z2L~>hYfgrrjcFl-NN(a4i;WXRj&c_a2m>$1z!ssb@VrJqqQg@HdK@bqI0IR&S;g%r zO(SjHkrL&m#F>jTj}=7wxwV{kcWvB%Iou<-2tW{S1r@3HRk6~g!$%c+3}`i)JIKPu z=b98b#RbtMWJ;O?3hO22`Sbc6>?8XqN&$6`wLSskOm3nHP8gBn^pe>vai5Wp#5^|c zG&s;UFnSwN8R=U?>|0DsOlI(Cl~1aZPFEZo&gNe4)xFF5It>ao_C8JayKF0ehrlnN zm087X^c%D&&TA|H%N6DIJc?)LkY3hvWDCB!#U?vLdpWboqwEZt#7PE^)}YbyUM?IV zyhYt2@}RFjH(gA9ieAvSFz?Sdes}ne>og)0RWoQh@)n(> zv`Kw7iAjX4#>|Z1xKOno4eMWj1su+pPIR8rsNSvtV_@-jDERiesf&f!ux-Ur@B-}O z`#h^vsCem@5U!+fGvi(JmL2SE@!vz};yGavge7EM(2h9L!9&i1Bv-@U^u$8nVDcIEj%tn(DMKF~KcX#^tGo##i0vu0k6t~mU zq88Gv^?AA{iEa>gt&d?IE)6>e5kioaHrQO2Ju73b1 z&`sudOO@sINzlT;GKwt5dMRF_FK(|Tnup)e^*Yp)=-3;G1EAf1B%YNa>#S@kr=lPB zyF9t$R+QhDutJ*XZwYwZ*uZ8iwh*MZgOg*sbE ztD>`{(<4qY`a-c0xbqD8kf3%E#!eC5fe5vwc%)47xhJ; zn8B9r?}sJX(w0o~NZOo0rVP(k*Hu4mJAtI58-z#I2?!pj39P=Zz%mxR9T}ZF^5xAU9R|u9=+-h={kCbEZ?Gp6{Vp4ri*oDRQjfAaPJu{)bo(HK z5bb>Pyx-)$Vqz_m>K>bvIXTi5ZF(VCI+re3-mA>r%#Ycfl)$__87x`g(kTh4M>|?G z_D|8>1FY}atwN=C=SHY5W227HLC~azcz~tz{ zGZJGuv8EH_=|jv(9+}qiG(fSe$-b=TT~lQlMb{+Z6y14>FmUus2rW{S;a0*rX``uV z4Kr)YoV2!=)JWoCWTZtN!`DbFX_VWJ;c1PcIf*IqM{SaCi zUI8tC+}NV6V^M6iRoa@utcbdLLRM zsj`}p(Mh{*Y}?wBTm(-n0L{Qd7hf}Xyk#1?{Zr$@xwD3hdF{`IcheX{M2C8EqRqL zM)EI3(^A{a309{2X`l<=FRDF*G?b|CT2980`bdv&$-6g|uzO9Ex6BPb(}c$TM~?`) zum@!J>5OMyUfsOY%c(|EBy0WZhd!-)>$o^>PSQ0$Hv!+c&c%}JN>WMWwy2+D0hBR+ z*pJwDfBkh*#L1f9{toSVywBmNudNuWFsP(4e1+N-S~J-5;r@Ok8;XG31E!SAUVCxV ziK`g<=d9AUl;_KSgshtyHC%Y#tuTIg4?U;-#cA{}=#>6Nr|$cJg3EwFgWYzh7>nqd?({VDN(+$+;!7Mj9waWV;|Cx=y)-QX1%|MtuH?he{G zE>Gg5jMW=&lHn_FTB7cLCLSO~OGpP|^JCbxa>9e`-5oC+oy|RJtyst>-1RYjolL7) zzZwd(fl-NMafTb%*0173)lyz1ZLF%298MD1M82VZ8-7jCV|M@Jj5&nF8x+icOM~sM zX^QDd0G7O6M2Bkxui6Br?t3e>g)ZJ-qot4iw00_kz~!o#v18Xf?gEDlFkXv0>a&rt zunjFNZee;^7JO2Rx?N5Ia!D7cgq5*|7YlFY#HOQ1=qxRVYIp$TL~ph|x!E#tvI3Kp z=}yu6JPQ7XxSRSJ9NX;W8T#OV_Q?Xa#H$qUzvwwide%*k1MEcoDB*!7Q9O)*YHhOp z{enS%yEex>DH9&y1Tb7BW^nKleptN-Nzp+x(ai(b)LWuf|6Zh21`73v``puiHV9~e zLPFM^SUc(x5npBD^x8wLKG9p207AZkfwCc^%Vrct&-3m+N7F)gS3q}vYoH553np6i znDQ7t8k5`F&|?&LhnQkn7$?0RQBqhMJpMj{K?|i0!Pw1pP;&914?B@?ygpHaEHwqE zK%6XcOz*krmThKWPYDIM5&M9_nfr$U%T*AT0|kr$FJ+Vz$*uH^y*J)S?>%Y&sWvw% z0l?)`+0C>>tstNm27qyYc-X41*KFfmU+X#<5NU%!a_>o4%Gn$F3=vpxje%?Ojlmr& z;KptOj7DM6)XfAUY_P>06jHOtVWu_Nk;&axv8PmCcIWi6l{3pkM_?|c2Gb~qu(#fx0Asl%}Yf@!1I8&u5C&XZ$7n_*< z%b-sgr4Oju)noz)Kz5Uk)En~Rg_VG~WQj*liza7`f6*Gifas5m73mi5xI#xz3!DMQI$K>13 zYq@oP0R{wrkEJ1Cz{?DnBWE{D?_`J(l;Go230Ze{ksKIg6fwEqbH_#H#L%$0SRmq* znUxhf4umOx)~eB13MH6kLAB^y`l!3Ki8owfjL?9hsOe@ewIXvbmrJzyqZJ=oEzr6@ z9*oC>hd;o_ufW|MT3nSZsh3;L65&KWZ#MD7SjaqoDK$D|+CzZ9aY?I`0ocSdP2WeG ziT-Fd=ulEMh^m5x5wNHkLbG{Q%z1i8C8Gs0)`W@%YF;BnN$9>VHwRkgHqXYejQFc~ zHlDrIbgVL{Psw#v%}3uh-}c9YA{PG^2amqZs?!^QV~tM${O_ykuRI;7&{y?f*;f*C~}nes4cEkWBcB1#10HYTdrLvp8x zXTLd!dPUvC>rlpy(0jz&phx*0Q|~Aa97!vA)CqczX6vHVOEIjs!~9DQ&=nT~k$XLV zWQ$}D0X3{iS8N;)FSDyYYk;=fkHMg7sdL;@ffZJw>2JYlP}3-u~@9~$zg)l zqwhAy#qq-vaXnb4|G-FhbRX0WA=QKKTF+= z1GLMUy_mexonJ|kgC}DBxe(X&ISRj?PXt{=Ai!OEQ6o0N$wNmY{Dj#NM?|GxP2{#1 zRGjic)(30~R&R{zA7pj1v(^JVH3!H?b~QDjKSTTD=Xh`*z&SX9f7cHhlfs{W>lUPs zkt{`Zit&TdEdTR(()?MO=item0iA_EFL*V@qE=+>o0hPxGaw2{rrSUBsWw!2vA>^- zKHxv3gK06N1zE02*m~=DFrHZ7y2VctBY5>GRGnnFSam=cCGOFrP-*3WE}0 zXjxexrSkpi07q@`ZPgwP4rs%FpC7_cB=C?cYe}hyERKMf6%#l;^eAuaQA#vUsuYo` zAU28|y9n%~jm!w1RGv; z0a7H_=_l-6xk-j(MfVDqk?mi{vZ}Gi`P*;(=-`(FxQV-e|Niz{3}@EI^Z|BW|JKKD zsKxr*1b@@G?|7tlFgDEiEq;)E0O&mjP`*eXCa=;*(`HC7gvJqr2NGNmK8m!oOj@qg z7%n$>NTqesdfucLX5P7qC9*!tCZHOTL!q`V$?ezjXG>ray-p zXVNY+G_Ie2^fx*|>^5XJVg{>qc{BdO(bCueGo>w>`#{QgDhd&dD;BCFgMef`8J2pt0d+x(XX$ z2y9IGoC*wj>^kShSGK)A{ytX3MmiHsB6^31IpxuRiSltlGFAJje2q`#>y)04Wb<${ zNY~l{!)Tg4E$P7=o#Lr3a0s(%$Y1FCha=pK(IKiz9#7QI>_NXAh;5ByEhu71zZwd0 zX(N8b=Gavsm4wWa{0;0iO10Jq-ds83Q|45*sg;FWVo-xz{Mf`vZi>Ndw3PaQ>cNm1 z_w{jqGZ>$U7Vyeoe&Y?Jc{bkPmt{v*N%fVEG~jdC{)Jf-t`Bee$Z5&e$N52~`YH}!4T|_%SPLi+PxBOR1Zlb1Y`p6>pqo(q`fzi3 zR<8E<`LAG0O1J|uCMo`VxU9-cxab`_1@T3HGf%lN7C{?fM`0sJEX>mqvlKMYwJM52 zT#KN>d@`Wtom_cN#rGRzU<8h$_T;SzB+@MrLKC>@>=pH^Vhsa@kMP0zxBP}|9(&xP zalBF^^^k)j|G(V5dt=*1k~sMPeF_RmJU|3elx!ysX;|af&WwMX*g4yonHLL?-A zVN3yB0JN=0{O(teexpHBN^&!Mn;nbjcUN~;S5?=eM1f@a;w9v+z)W3G|@7V_yC#e)>Q)QG76x^xC+UCyE@(cw1B}z)S;3;g@v3h z!5vTu=V>O2^EL9$dqZG``{Cii5V_ysc%^j%R`TS{;N-2^CvQe8GkaWbUi!L!msT0U zaZ#3awz%rm1kB#)mDm-7-djjPLb+aMv;0h^(-y0f8N(|@TRAB%0E7hW3dZsAF~?%4 zWQr<39w&!5;hP&kYH_h^PbP`s3v#><2W{RVmUi!Ag9K=FVoqn{1h-jg`cv zNht5NlGOvJPI|V;mv#cWnhd6YF*`uV0n(3m<&tw^oj~3&%mnt)EfXmChFyu0>}r%` zSL6UEc1=#Rt8$uM7o$(uH8I7mhbdf3PLo?wll3*+JpdbG^wkYE4^Vv5)zgseVv1^3 z&tUT`?Izx&^L$mCW5Y6>YAz#<(Mje(cIOx^sqV<{>7;v|yLN*;YV^$s`cJxL@%hI~Jd+XYtKluL0Hj-=to>4TFoOS&j}4 zK7RZ-_;`O%R_6zY-+c4U!KaJnase&Tqg6ahP$*E0fe_3R4IB7s3f^hAVIFz=sNiHsb9l&xd=wVSHmxVU|9P5>xb}7AEV&W zH(%({q2J#iUZ4w6_&5^P=o_jXKI8j3-$L1oz zNYT~9+lv&4NUT#}$oJ)^p8Ov%UF-`Ls$!^%&Z4d2Yh;bf0zFB;D~X20NTG`iQRl>IYw6)01r4vKr!Go{~Rg+-5`G&z97hW_y>U4MM#=~ z{4?6W4Y6BS^)YC29R0+e}fDr5ITn_@I~|Z_LQ^kDU-*4KU-r#mNp01Oh^YFoK*G6g0+K1Hi3_V*W_qTMKIW84TkI}EmX zvrJcYb|ar6Od$7(%Sgf_B zJcaKRwtPc>vxUHRv&w2?s;t`jh^T*Jus(a}U{KQ5{Gl0&y`)fX?gihD^(EISwDl;7 ze+w-?OaT^aJtlQB{0E(U#rQ+9--nVFRgQr=yANDJ)Gj9lADpDwnw5Dqg47n74lV}%*spJ~~{lG<&?jOb|2&xs3 z&)`e(6Y(OM#TUuh7&c5wQJVxe0^jH-WR;-H-4s|o*~1Z}Uf`o;e3&FNQYcwP=wOC5 z#Mz1rxb4v*rr+<%(M3%AScD=r$C3dlE>l;|HjvW0kyoY{QZrI=vy>{4RZRZZm*s-h zg3$PXkh5Nz>0uR9ecD|y_02{qYsKgl8^t)rg!-BJwMO#D!W5_-QQ@St$sAa~2D^q|vTu1x=M_3*fEE?d=-zd^~q$ zzHL;e7F0+T!h?P|hz`zU@490gou8I4g=cAvhMp~nEwo>wWUwZsKfqAjH=6h{L!829+r>%uR)ge0ZHV<(puZMbm6T&v)Vp@16{El;R^zt(1gP6DdPr!u7;aRNCjv#V zL4KBY#K9jsIAKpNQ{>EoU1wF%QidTL~<LXILv)+y93qR zMz=0dhAL|&ji4^g?iX7!Nda<7DSQr2nzBh3>cKY?%8>bfrj#j(a*~vP5R*;@)r9w4 zoC?|&C|j6~Um2>5P(b3N!SJFuGY!9H&}^+oc{Vs%E$3)!;X%$o=c4@=lU+%@j?d7J z7AOw4L3#$D?2EL13sd2siM}?`&qhNA;)$Iz2TZD_R9 z07_$;6ev1ypiNtOL!AJat8nhhU&Q00d~ZALMgV)Wjbc6H-~+ zlD-;jOM4FsJ!_gH3Lxg26%pd1!+;4WEH_Q*D3h5%5$$JRvc~y;Df^7sd~yYK%NL&Q-#!S`$|t{E*j|sk?LU<>G3`83CyBJFP905<^WxO1g-@x3?=GITCQ6#YFrSr>!)0KXv~o`KFQ}= z-^_xZ3(oz0=}5qUl{9KoLM_uTDT&1N#Qc_TIT}|GptX~KNNMi<-6GYlBbAY_(F3Ol z650q}#9FIzC7}<2PHml5Mv|d)+X$M0ccBInEiYLCGer`ZOEMX zF6G?DqZY6+lCIT|RQNSvuUwMaixwl>+5p@6D&*^ShK8*8RimyH%%nu@4l zchj{yM3hW7m(?-NR#E#i*>7U4kclynvYHiat+R7;!-_P{A=B<>)v*)vlJ@^&7p?`kMmAI1R}2VMc#*#xlmm?y+X&vRsdfah9!T*fq`bx>1tS3zYkWOcbV zTy0RAi`a%=$B4sCfVJC*zHA-#ZF9Ygw!BqZc>3A%Y<|TAIJjW!LB@?AjRy?6Ks2x3 zD^M>F(1*YeW8Y@64&N3y2?{-z9hk>H7tU&W29D4)t7p&J7((Jbqsb?U2WzO^ zTr!Q(L7qi+wkjarXA2hN#<7+5swzJhilD~G^j z(|9~1HIV$>NQAiKf;CI^-S#(Ls@rY?*Jr(&iz3iMhxBunde}jB>t)+QVed}aJLD#R zZ^msC6mR1jspBsb8Cs0kZVoDF#qx9rNsqre@?ys<8b@RDunNl0nTU0_sSE9ZDo{3| zGGw3Asu|UgbtQeJL?n+qJ|u6b=wavu$CfsQ8VX_R^<&$C_6kbb5V_o7(L`%O<0gtb zMm;NwSt<+;C6{$Pu|B7x$ut@R`GHM;m8-_|)tP%$78-WiDFY10^bQ*j{WxnVRF%E> zOfVBJ2hk$QB{B-VH{-FwN5+}%x4?AJrr}0i*so11?m`kqv6p>mk>7e-psk3YD2gnb z*Y7Z*m`xcdiUBUNYjKB<4r6g6j}F(0-!p-Wkfqh}`O33H%PDGw$}4Xc(p{E+ZUE74 zI~7=Sl&ZDTDX>!Yo<$>FeY;~sA6Ope(5RWLc~EG1RotcR7|lYg*2meNY+oGRjE?S( z@6miVXX6>kCmx>+9G*8hv03#Ki>oG$g~~}yYGS4A#0Wj|XYIp?5kK%@6#eJMDNJyY z@aw7b(rr8fII^IA=BAi$-pVI`ow?d=v6>LlF0%@sPw=w4chC4hLDsSJ9Y&*}`7Rz^ z&;7Ut-|geM6mkwtpD_)~p(&EerHpn^C0d3tu51z^zL2F#oJWfP(2Q27xuf1bykKUW zKVt0w03}@9!m=s)ggv|b<*X=nI*v~ z;^J6cfTNYV3K4?%TRf1@(R|-YNu&7U-o35fo1v*CBC<&xucm8$*WTp$Ii{n5Y5|){ z`5r^|_YId7Qk~%5y;WF5@k}Ubz|}WJldO1y>uRg*S;rX~PTA!Ho~Fc_E?#Y=B@VRd zf7I^TX78{3%8BK~%iIuuHX0hCg(mI`Et*J-d*7AHp~|KqV(OyQ3RHArBV36i=rr)b zQ7w3$l`a77<6ew+*&CN6A-Y_5jU#c$puHtI1UC?1tjaxkXV`|5zH(X zu5zMif-#r<+LyG~Y_zN{2z@&^c-y!s2<-~M&T*^L={TV!F2{O*aLI}1N-?gJjM225 zJGt@6Y&Slbo}a@8%TUYbI7j`+ru@GAC>5MWm=sTPbP}{Wt(z*8>PgXb?V8VKNv5@^ z{`pJ&F(MGUoW~ z0%M{QD0)Xpp=-c@*T9cJ>+xQCbAw)*Fx9Ha1=p?H&v57(7l4Zj6=D|7{NBMY^-V1F zu*gH|&CL*1^~QzpQ5&M?9n8o9DJjFdNTj00Sig@dnEAbXP$kY$P85;5S{bxFR7)~6 zpW3AI075{$zi%ac;Eg7gUcADDZ0Sw}0G(uG>~S3BPm1IGi=-G8e_tf|SZ|jvvx6|- zH@)N-p4)nDgGpL;!>u2#xhe;%geN**%0=FT3^Or1CMEPVEbEDN)QFIi#AGg!!R3rb=^1Fhu; zy6jrXkE5y7c%7ti9lJ}|vV}F5X*J21QshXOMo7xz1~%KMSWhj7Y_V^R=s}riC$xne zj%%#~Sxb-3Ew(+M)KebdD#71jL#Ei1bblXUAl7HaM_qp4f3!>afz!rww`bx`Q4hnM zRr;r>)4s>heLr00VJ+u9LFZN$GFFQ8LEuxQ&-N2^j~J2;z4q`nUF!{6zR%ECqPt_s z9fL?>v&W2LsK~S*NgL@Rt8*0ZRIx<#v<_}jxUesB002h&cgP|TVTHXRN zk&m6K-xHi)S3hRejNGrgRe2%AvB>!_yN!@Snu)}YL-g?ti3#6e(Ma$|GEf7K2V*Xa z)<<}_Nvn;uX{w~PZeboD{PRFetpbu6?_tYNHf}7~f4|n9t5IXCy$srm4+K6#O=+}o z);C)Z4gJk4RvpW6rhvkKg;%@uQ|RWzxswo$qs#{B_43mQLt;|P`EP1D_qWWU4`>IV zGEPDE*n4}KSfONZFXx{I)=?-2t#ycH;~$KB+`$kI5{O1@>gPa!6*c=cm!$y(>0#r? zQIY^!f502U#6_v`eQ4q)L`O6k8ZD|AiD9!wwCI^OV=YU?vd|bWpk#*IG38%C+7$5T zXu4LkOzK5U82^~Sb{x>3UN8!Jfza@&ObwrWKdB}qqN?E(12CYemAa7eX5UAJJe(C? z>^8-uFF(t@i163VC#DgnWP*-(hPWW=0P$+af4)E1kLN-)4e4)gR(d9mQT@$L8CGcg zL1Vz{wi2m@PL;RlOkJU8%1FeEE@{3g>J!L(ZKMz2o^X88L@n}D>`xlQ)S@bdG#%e0mETgJb@4rq zoz?hhM{3HWX-ShIUHGsF53!jTC8blx@2^L%46Q3f+o*x+Q8>%PLMfb0yWHB+!1O5S zj$fc=7T((4%}~X1!m+g4?&s(lq5n~se`F&c*uM}4(b1N6uoa-CP`PsMjG?IX05ZcGpAOZ zC1#cAnm^ukpx@?Bq zg8m%gpTayjh3UQyYxG5vt7|gfd+3tUq79Y|Y{Xh@s^uw*f z2S1VW=L%QnSy|wP5e7%|O}9)DoBme%Gt1>hpAA^tRJ1j5)5u=JO>D}ge@dF!P8C!- z-D>k}R*KhgPN&muQr?N5p)oGhT=61I9VLZ(_$iQtfs^SQcEo9NDo&Oy^ooNaV1QE~ zo0p%0K@EF)b`ho#s-Fmog-DMv-GGyShSM)UzxgLxLWpbcG>WdVZ6(*jykEkDbBwLT zM*>4yjLkBs@5-7{csSCnfBGrdZ`NAoHBW+{V3VbTx?BNsgF6h4vC*Y_D`V%c0!;~+ zo&{e8`|~(B$CwJwjUorX)RX=G^p_gzzP2+kDL`^*a`5VxFT>|(FnJKZx_KT=zWn82 z`bvGi{^byV{}R&IFHmk8pTprhe|#oMvgmAbJ{6*}=r}Z`h?o-xf1hL2bEp)J&iD68 zx&1j|Xhp=LLQZccS;y={x(H9bGX*GKh?)9fA>r`l5TnAOC`I|{%2hyv+2mphSBzYw z_1bnKZbTiR_arOqMP_+xCRT(Nl`ZL|8hsJzM7W8R{J4lviA)z#j;^bgzcQIc9t?-* zWzH?6_Zd29;6g3pe@Voda+){P?+<0E7?!q>y}hb9s3K zU(4oZISXL#Sn>cp zPT)K6=3?(j=710orO=A;$26}<2E^XQFFmhv3mKe%#T1z#roczEH88TNkIAw+hjR;i z2-w!`MUepue{h&w5X0HB%AXuB(BrB9+Pq}uOkbNA?icT@j`9~Uu8DJ}ezcq^Ipn-~ z(K=~-(K?BE(aI#E#!t!H5<5-e(Z#`q={%{gzTlwPAF?5NQ_FAuyJ?nLYnC*F%Jz;W z^LQq1CQij$3o}|(gjXf3K!4EiwO_NDr1JCBKehcnfAvLi@l{zqqOc$QfL|Ia@Zmy5 zxj7Z4qq-BBAbOFXmF*Eq^aC(NXM4Es;7gWao{R@1X{4MCQ1Oc@N-NTSie{v^JOCy& zb>b&Baz3WwMyH(g=B6coMN`uQi|aO?2rMCTIFYjE&~C*{Xt9bbbt#s>A@OU|dOGq*A+7L5hG>ng&dH<>SP=0*x*El`n3otU7zxl?y+Mk{uA`}R02PxXxEh+kl2W1N@yg!H ze`@e&IKnxMaISr6%%wbZ8J{Gp$sDQk8T`Qpm&wWT_0v(CswDm>6W}_&kp6jy93eH? zS0hVi6Tg$+4yuX2w=>q0bKAknG(3q$*XigYE=Ff4-)=^WH8KUt$JJ8JlBwb)G5dl< zzHUZoJRhB*Paf@e+pud@_Nm_EV+c{de{zJVZ8>Th%IHC8*{ zI{2a=bD-IS8fXPXW;3lV@-R9+e;fgxQfFj_XQYK-H^$IhY>uJ1&~MqO?nYP7MdH&T zuqYu8s${32X$H_}2udNP<&XPwQn1H}iz+v>a}gB@4J!EOM8xryfZIzn(8?ru26g`*XRQ|b%GyPaKNq&tD}w<{(+m#6k~)Nez?}mhFmlWfuOb*amI*&b+7{~_^a=a=1^rn;@x5dfc243p zpcYZPXUR$q;!q9Z5C@@Ne*{0_vOmRte#C$N1*`I}$5(Py{v}uCP14%uSCfBDkL`Dc zHr)kR<(m*o#vkFIX#5HOO>hSBQ~m|G>PNW(_`oaH=95~Or+QUp@sCh~?k*nHt7Hxk zSpqO#$w%CIy!0YtkAjXwu}+SbO`S|Kbbv+5CrW|GK%V+gQAyN#e>(gMAK5kSq4nKF zkwhOpm>8$+2S9)3M1LxIPY@|t4$+#6M7-%qTvJNJ`Lo@C+q9V`uf%SlFed@fu$hvdq^Qviv@r! z%R?G1p1VTi&{Raue<9`Y&uJtIT&V(wqALGX1%5ROnCWs@G{O3P_7Ml21~E&sIEg38 zN!0HJRfn7_JLiHMCf7v^2GzSpO=!UrQn}ddJCVDfT>fb_ait0^L=*heD)cKsk#pQU zn&7*4-{S<=d9S4`S5tAFi5;SfI?nze+ZYplc5oFOHjl@K}9s$J(s16&8xwiiY>c=hdI2NJP`PFp>%WgoKUi><4?=^@2&pY%KV zg5l}y(LSvcGE zSzZ84f3B{{{}=->B+0;DA#ERi$8&6Ig#CXTjY)*2%_uID&(}WHGjIT*<~93u-`j3n znVZ&pxns?jV-QB5sj9hU@j+|xCzq`oY$E2mLoBt}6rA76G8qb_*e z2MX!;?mh&S-#uiXOz&{C*D*$3E5Jwaf7EuwgO^25POKd-PI}-`Q_pYdy%2R`Ee9uU zcPW3V%GFXQ=t&qJP-YkTV*a#^GEeXlLwy3XFm(B&Je~<3*;u;9>5irCcCSc;*hDo3 zit6-DXqW7AgkFcm<3HYL+vJAcO$!w`8&IO*wKz2xkAv`lr{8LQ&!=o7vAGlst2F?YOSXOz$v4jUtv2(9wH)&JG=y$IOQe-%=VDJls6Kw*s-f*l9L|%`@0fH}-ZesvNrkBeFT_0`} z&sKF)UYa0?aUUHTPA6?=h00-faqKwsDMlivI&KlLmCUp60iR1jy97`ue_}SYeZ#05 z0gI$(csW38KL2+TJbn*~7DiS+cgQaUJ69ijub;L6BUfZSFj>X98WOPNjkQo)Hy8qF zANC0<$StWE<5?TwTXYN~U zY1r-fEzhHl4I|xx6wcXdp>ErqWFgOhMcv!eQ^~P^2Nu8Q4)kn2r$5JUm=H$Th~v0v zpMTTStH&+asL|E;-1hc86>t^<$DiQF3c}}?Tv3;Ymg!quhN{&#e|9fURb|Auh#NX{ zU8u@65qR#{Pp*&?;|@mKan*&sQaa0O2VNZ%7jh1gl=69m^HW`xxI;P!+d%M{<+IQe zJMQVXuiv~gV#Yl^1^$GcgratYxhG?b-g6x0ZYC8wfDnyBJJh4*p(G%C$l&Hx*84x{ zhxF~N%9oAI>nW^;e;!R`XbW6>q9C^|yiI2QL91@j@;ffM$s=rC@2rNIsx>;E^4mbg&TIxtIOl})Z99uMJC+EF3qYtSov}p zMp}O$ww80`v%s-M7D}+7bUD1;Z<4~OnjP{IwbQoBtr{W<3{{c**0O?pAAMu;I8!U^ zVbn>gfBU3xg->eZ5mk?+%#kAEZj7MV9gwkz;tHKU#=?6!Y#WYaQ$>+x9K3jAy;iPm zpBi#q^}F*y(6;*%sDL6?`@>jgmct-ztdEfh#w)c;#TB+1)ED^~`f64B2}%TnF$?#G z%Hxu7s^p3XO$n1Q_1#GxzC{Y|$QHd4#WJ)ce~A=ejluuJYSGv@Nw+td`aA;4%{0l; z!R!eK6+I>|XTk@7OjK+#OXpN_tbXdj3Johyj&?184uVtxejh3EjeArWphcmcfziYh zE=J!D3-7JwD~>F>^O!;1q1$(>ym}vXn^zg_*BiUs#wSyn9$5?ULS&X}Mhx67>+^eQ ze^+EubWdY=iRzhZqFN@Z!CJ8=nXJlZ?9=&O$$A0kx?Rza($_O0iA7mh?w_4 zxHG4F{t^#M0S3cWns9Y=uErZiZ7qwpS(YZmgdDksb0t?6#HkO zlGfwwrqe3;S~^CpxM!3KL^z%k=egxh0C)xsApopN*WPLBU@E@XT%it(3LouLf809i zde22hcwXO@@7xSX%f5Gtz1NwNY_*l)jLRw{P3WoAm`amwZPFdoNSoav=(b*>Sf9!l zMYj=AbcJ5^o!x1X^}%@OxA_*ip?Pm!;+vZ~CKvMx*ghVGTws$ir!*8bmme;Cz%~u8 z|5{lpWJyi-pX6m+YI}(o3mLj*e=nwVIc?S!aQGtiuIxD+iiY*Yt&OHz-gEyE5$MRHSj9s$GVYQVkQ-CU1jU>Ce^z*aEp61?=rfx<<|$) z*0zt)E*iFi>z;`fq&=;oAM1e0A*o+<728#vH*VIziF-9w68Ct;oyy^sf0nMtZlGr%O6AsxF%D7Pt>{@rE$^p% zGShL&`j8Yt!s{Y^m+&~~oGbGIsnMcV>uq+^!>qL5l<^h!Pc6sL(#S|ke@big=I z(qmu7C~N5^iTg+Q#SH(7t(fXAioBNo{~Wc-0*<<|!n2MS7Sc+RA_QW(?kYk6vcHJo zAC?;w5w%4e6l6f-D@aI>b2R9RZ!7caq zk#tcCv9q`cXG*`CJUf%_wnt}GH{P~W&!GoT4kw7=k-(Q70^&M^2>IxzC5PcShyQf zeysO~V?_9pZ4rrwTHn@{^lC}{xEV(pkOL18JrH!k7voM4y^nt@SElyn$QH|*JcSXh z$0PD;NYWw>0(06Yu;(0!v=gi*I}VV;65kwhaM2wGiMuafb!$ zLv;YihiNQ;f4EzP!<`s*)*-8EQQt1*h+1tpOometPy^dQ-%hu0!dIk!DBEob6O7}% z6ECm0w&Jm`C*ElKQCN?wm~#7JWEoqTl4=8g9V4@Be1{k$WrT?~dZhGQ@c*$F$r^Z2 zFjP$1g$9O<;*DlbT@AtwVc{uY!Mw3Jhhy&&`&>6Pe;Aa4q7@pk3}7#7uE+q~?=UrQ zYk$PN5@SA?La*XDt!*m$NlOnn7RC@|o0v|t!32fQu^5TmR8~{U-IiCejDwKnov%@& zAt`s{mgWcgI1VfFf7KcN(4x8{4#RpUI=G7B{vk$yV?tP4AfqqpeB*1k`J&xNi|;Ly zRgr??e{{nWNUUN%;x9uIm@1KZQpO(b?bIsN$8vE6#BX?=*CVu>2fWf(a|`0r z>>~Y;msLHQh?0X>Sy`x|eJk=YKog64GS3S*e>%#TJ1TVD4_SFUQEmZ(!(bg-UsIDj z{;n!7pHatT(w?&`nSm&ejt8s&>Tn~KxcZGfNFJVBHvnAF0+;EbC0Ny250)~YHG%Zy zwghVAAERN6e}6_VOpWxt}H0 zvpM%8CxN)ZE%8&aaLNGgTA;BT5YnuDWbew(k&gcGc{nl=QwUe@YT>?QoNEk_!55Sp~kzykn8)Ph+LIZ7o*5|Mnj}( z>>Y~8^6%x5FH}I+CNwrlADPsy&EMUqcjLOv`VNTEWGtkv7(%OztFefdCJ$1ie|c-9 z(-(=vS99_-GJvb0x_S$E1U1~BE*4>cb3k)}Ej@gg_)b5TDesWp{afZhzxu@!jaGq;(= zQ}mqA1;xaYt_*3H+yxO+g-=PETiSZT$BRrk-SYH8lC2HZFH5*8e`6cZU;pp}Hp7+f z-cEx{LJwxYu?@tfo10k2ofyhoRMnABx$$bz!GWZYm zs2!=-L3veK3eR!meqMLDN8Y=EGi4fu#D+-$WF8L$DsV4|Ss2AREiZxj1d4TUVf)eE z8|sc2K#A>~izKs@ z_Wi_SB*Zq!f`l}}p&f<=f5QnL9%3M9BD>$=)P!rXl4UypYOVl~txhag;z%i+#wbqo3TQIaPRG=B@BDuL)7?IIPvXGwE;R1+4_0h;{ zvhCHlA`iy#Ot`h4CB^aL@$k4B@aW%_%O}H;@%32#{%gi@JqEKye-2RR&rxI4{XRQu zjLP__YX2Q0bEwMnW%zTC?akG4Z?r&Hv$&N;joeebqvZF`6yPi1yntL=>p<;ByI@8uZ@jh3`&R{fW!H zUx>?H^(1b2k@2(Ke^(3g#izMTKnnfKa=t=czIhVlz##VLfSyiCO2&|;9BtLA-Gki>fyoiG(L# zUdtmf!c*dwls2WsxxdauKA&gB8YV}bKc43wXi|17FieqPe`W^wo`7P3U?3;dmsw99 zAIRPwA3&qC*INZMOo#)B9Xgzis5NS{7@odU$VxG2-;I+X9%lz<$8PZFbYmE0+zA7Y*rosFi-2OLVKRkBoI1AVt@Q7f1^mqQ_0YZd)Dg3J!d!Q{MQsj z$t=JrQ7~nzSLTznSVhg+Bt!@TpAW>j>fp^Ngc!DYVyvqJMI%SB9PR*6{E*H)Hiha^ zQy#+fO{J1xx8}`jAuW6J^t*%~m=Jd(8{KM^`8rcmeXH(H*?TkIvk?VGrR)sHZ!_Cey6EXTep}S54&@2UM$`^?i&Uz9A~!2El!*1TjY%a z?NCam%`6^l$OE&lH+M+w^QV1>*l6?KJ;5tEsEAb${dJ-)6uimvF1JNhOvO_<(Temz ze_FT+IrSFG@`_4o$&m>RDJQHilg^@=i)vpt+bUrpiOr3^)Jt-Ahy&H9Dso!RuXK9U z9?Y(-VqtHyG+I8j9&qmn*B#)PIPi#f0b}CM*Tnsu;Op+H8#b+;y4Ik(aR;dFvA3Nj z3&Pl={8A>N!U|4t)K`ow_xe6+n@Yu~f9=pbE~PA?K`Y8hGbN#lpNts$FmiH@;}~^~ zh{^p?=UCQi<_=}s!cut+oCZ;A;%X?$CO^A+lVOlmI{So}ze7sW)$9<`uI*GNdc?G- zGIcQlCreEqm)uOa!?mFY)NyI7Ba4kc(0siAf&DCV-Wse_z;# zyS}jJ%4w2#OoQ3S#Lqb3jMKSzG; zTcm+u%Orz`B zs;bM1|jaLPkGZWFJ`A zcr;%|9$3iG_7vBBbOaDV6;RX^EarW4V%_8D>l!hXtKj%lSADmcjZl#CLkVa*!g>N{ zW*YU{v$bN(k8qccbtL&wfBz5@@E88*XqxMKTNlk98qJEN{-M(qcHMrkXyE9cXI0RH z88+z>63X-QMP|HQv>z*Eo%UmewLhqR{lLS-Y7$&u^RM+fFa*0|s=;L9NQ0--py$8? z3Rx0lEHb|;(#w3NONazj!04(ZA+p^U3zn_UbTL~VjfIM`UlK9Bf5iNvWXgJpSvWgG zfX;XsOL-U%EKdxFw}Ouq5uFUnF!tMD(yZNif2)@@q4@gr)yp5AzI*xl)ycD;zJ2-ZeDg3KJd6*cAVyb?y4t&!KfE~k;qB+(Sd-+W9_FkHs}=65^uOxyD?hsLK=f8>kE^4$1P&r%O%$KvXY zyB+WJ+6Mzh*%a;8&O&siUKeC}fQH&#<+eRvcD)5ouG!Aa!=N+0G`c36Rk%)uv5HZ5 z1bY?8Fs{0l$=T4*;lp8^r8Q<}1OHL#?x;-~ZyNH~54ZO;UGMPByAvoK?q3ben7DUh zT@2BNncWeDf1UhAYpk%^vWEcv;ywu&R=0St_S^~nvO|o2X5UTrTRNWWx=~mF4j6O{ zb0aemU^vn$Px}{Xy)2jTjU2%Wea@Q?+JyB}ai;hon~-wIp#aWQCurn^09_f8l2PiANO_ozWwVo_gCXz(itF zH0e}TxT{s!L2g2VY1H?>KWAtSuiV5tdqqotjewpkM9r%#6emED2J)4V4X&jLv$v>t zb>r}S1mE_^qU)}Eci`6YOIG8|k>ffb@e@iOh0aXqcL9fQsbChSa%U`-T~P0+r{|PK z{&rkyf4xUkxF^SfjzT!_&eBWHdmuwl)6?g2lOtWjKU(lH_z}VU1E8dDiNrzMt}f9s zoyr^y$+D(je>m?UR!iK4Li7e?VE!v)9X$Z54@v?hnVr>79-kAfm{xdyV1+(0B2OOU zJbRGy!`HpT;o@Nr{_8*d6)8r{fj{Rs6l&stf0{dR$I>A(uttUKZ3Rp=F9Z5mIGiArM%WIcjN-`yAOD`M&-I+zbo49hjje(TXtr-?^ONnsYS1?8{dR z@jY^t=f)o|@&-7MWjf17MTrK6JYZEWTP*Tro!7v{e&SmaFT*d!r{$+UtBH(+XaG{2 zf61*~R^EcFPg=66ydeS+6$|L*J+S0l7`E?nk*Q@VU`=(w{vtii7JZmf+PF24F@FSn zc`NY{#T>Y3qv2R^^e76dNESBSI62Wwv~F<}YJg(H2pQ9s=A?khSlrFPq9Q_Agooz( zw!$Z;xf%AZBo_wTX5owNC-QeXgT1_%e=Sz?Y?o92L=7AEdC^1SB?$z3hk1~Q_{do& zn!u&Pk~;}NZYxUB(hY(D&?tzO|7I~oVNrgMd-prsx)F(4#OjfRMV_5qL=sXSAQ^U> z%2L@tB-sU?iv+*?h-D`ReU}8clx+B=4qC!x9!$C*%unM)^vEATfSWpi4FdFSe@;LW zKUs#7&dXwfR=1sSB)S+AdDhwdC2T%g1I&e8ILpw7epX=_;}df;bQjVW-a;^+5`N%s z7WsTkuWCj_jFcEGm`Y2mIZhQ^9k(e;Emd*cmRAByXm!=o3K~UTcxpAEwbIUqeUh$RgR0*;+h_7zJ!kYWN zOJvp|rE(9{hCX(X9PJ`{a$=z8zs>1&5LxHdf3ioXbi@jl zaaPYpLLsq>F^9Y4v;=ZY^5*#XB>fRUJ4hLIv+b5Dxw$9B5{70PDuJg>TQ%B@Ib(5# zV~U_)HlfU6v*xXl9NML#KSBoJ<>fyg=u3Yq`)(B7m4Ww6lo`iC&hvCG-5pvG5x{r@ zd70zCWHqXFBBNc*`K35re+d2hED}cW1|!TGlI_L!81e_fxJk0(Y(Pln=7v3r$~_qd zlpI8uffuuo8XyOJi4l_n73I768y*ks{mPjo9b*~1vx8RhS+!@!{Rg8*Y-2{48`W{T ztlzaDXHV#rQV=#N*pZ+2?g{r3bfPyY?i&X|h?e-Aq119wqdlqjf0U4O)!Kq19oOs= z5UX>*qv#%LlTKLoYx-R{;x0y598m}qPY-aQ8Ge`z5mYAonhyHhTS-8(< zVRQSMXuIxsfL44C<;Q-;XG(H@r-HKb3L?Tk&t32>R`lXqogI5OX$whR=7o51vNjowOy|W9U|UC87S%iaYWZnx z^ybQ%2$$EZ(+l7-BB2|^=tN^h&DDM!oIMf&d zqhHZIe?+&ryQpP>{yhzkPO~#W^LG0p@pduKx)kvGc_Cav9JA5IUH46yjFgVsghe?k5PAs_N@AV?(f}=z2Is2`uE) z)=*M)g%9}du8r|v@h6iB{+Ui68^_B&yn68J!-8S=QTOfUu1#lqN&px+?gjGVd7duH z^G=bGoU>EUUNBocq=ja7DJ45&uad?}j66{~e;N;z^>gxo#ud2(X>qO?Q9Iy}ppA@o zu9mSjf}SI61~~3~M($d%H+0+omXpH32CJCbi6q^w`Nyb5;om_e&?=qwzO79I$S`mlW=8~JT)h>OsF4-f{Ra-ULF4IrGGN@-{l&YI-=`Cg! zeE#_1vOZ*A_3sadQi)?g$}2fKF^GDt+4#z|CU~uMV?;5aq699#8d-U0u{8FT(z%|t zlwPKHrk;ZFVECwx#=k=op3$(je`sGG+pR4+ggbYUl`Gp&8ayMb4`3Rro_BtBvDwuOW~8vlQ62SA(1RAJ1v-6cvhg3@ z!yUmWuNEm83WDy_$w2Fbtew3LwCGB_!Sa7Be1G3=)_<1MQbA06t@XSfesSH2pAMs* zvfcehh^PCDX#H^a8gO2|e|~t2((QFu+w;9}jUey!>_6f8Mg4cHc(3 zZJ+Ji<~MDZUAD0+W z6Bl}h(rFYSnzN5He`!VIY#0;)sr|0j&9GvsSi*u&<9rx`{ptXY$$k(8V;Po5wUEdZ z#-Q(1I>tP_gfl@)?o*5s@#Wm1g#KYuq&FAf*0AFm18QV#!BB?bELy2mBqFi;L^T=4 zy7OgJG7cf>U75Q&OjX>`t|_&*$M!ld7-V$QR$ECXGg|skf3ydS@?(He!8R7UMBga& zwn8cTHrZxz*42cp13T2w^1>FqSkb45hB0Zf?XFSk1-_8(C`9AJrU;Gns+WDT{~_}q zQvcrY64`!!{MV{(^0PdfcfU-U!Z=|YG-nGoMGUQK93QJX(z7m1^;chN-A-(mx}}wr zmz}owNQRuvf2#Hr>v#&ArvLR2iQ6sAw69T@BX!!n?`_x1J^Nbsv)Mgain!hfo4eRy z4xQ|EyQ8(Om7sJG)}L`(TDIDj+ZxIvLNtn)E4&XItGD0tj7tbfkCvaJ$a=V?dWR2p zsCUpiQdKM6=gxIo^Af6r-4h>V^PCj6uFc2kqn2M8e@t2r;6BxIRt>ZCv@REbmB^!w zGF%%=1Rf`_y+mJX;edOXMkz>9E-^YhmYzW$_TlK0jsbM=2d!r?&;B}P8NJ- zC6Xu%mU$6%kMq$j7w21GYoy*2t?ba;Ya4wWiH3P3xaAED<2hB1NZi+yD>dKcuzFq! z>>2lPf6D8DNQ8~_9%#Id?ZO-U!LDn)wQnqGZ@m5?x{mT1k8afQX{*CHQ)pc;N%DE`jxCs5lgKRp zLG-8Y^tu+ew4b?!&982|)KX7qc%f{1zv8>5bz>N7`lPkK9a6IJaPYA8ibILwy4=|4 zf6nVp@wa?;$jC-J z>s;t8KMLEWCau=??R)FpVeaDg=A%yee^Bn$?T!m)ii^X;ua}?VKK{FP1-t6)vX^aQ z0oCn7p`CNfJ^hv1)Ax^@J#DDSi)XA(;FG>D!yOgvqcJN0=f7rrVRa$5?mh3{?JTJ5&iYeOkT&anp!hTTJ)r0dvZiyxF0cw4?o%#PZuoU#BmHXQ-e+b22 zTlc%m73^|R?AB7pqTQe4%R!9)J8Z3$m8mEHzwnB*T)^CoSZhC}I9n%RrE7jG!BCR; z^$OpgLJ7IJw?wHr(YbLizr4)mxzxxL5_dj_aZggdaZeNCkSpW}k?UQ!=4%yRbnJL zDE7qR2u_7N6V&=nf)kjP@NZl6SI`s2A;}utX6#e9f^A0LOy1$IKq-#PF60|iOO-u8 zgQ=g<2yiW2Xxd!lPP*`-?8cS?@0*vCVDBz9R{;^+qPGEwND~xAR?I~kfA3V1x_8T@T`roC; z0e}?$pe)LGpIwP{pbq{kyLwJ*;ktAQT25As1>eOCM?3=D$w}=dHz#bxQ@rPxB;M+q z9#8SCZ1r)wj+c3{L#f@Ke`5WCEy4}TEOMV*#d(`g#K}eRi83G7Cweua< zcsiD-ey76vHrT27r8V5ARh3>@ljB;Gso!`2@qovGfUhsMBZz|&Dj*+}nPA3b8_qJ{ zPNjm}mjG<2VchDo`zczU7iBR#blt6xu!=mVV;o)jaZz59&(e7|f2-)Yz>$LSu=?I= zNd@5#AWbZl7e*<3?-!pfMSDYg->>YyuT2Ut0Og(A>6`5sD`uEU#95rj_-K2*{Sh_W z&x@|vmfBToPRSsvySi@dK!#m6i$__asy}I~2VwXP8FuLUogI?-p1H}>84=s3HOB1h^iGvp+sS9EVgIQ|>53*KtAlc!5 z@P%+UBiH=iJ<$u&I>aG-N_2UlBk@s$Gm+dVusg#T|7&%vf2@$qxpi7iS!PjRHl~G; zAj_<(^~b!KU4$Mxw^+s&7uJ2(v$W0vnoclMS{SqUZ!slArU_8{`!SWG46D>XoDziB zjC>#j(X=i$+VpIMkBJ2x;2H+(?T~`Mi>2-c_KCR|C!b>fDv44e7eMzZ>H9L$PqM;C zPrkKzoXDVZf1{Y^;kif?=Zk^X27#<9d$>(hEGtXBrE5Vk-OD znBxrXc;2{)0|AxDQ2uewZ_Z<_lUbW|6MwRCyArZTP9r2sV-%D6Wm8toPD8MTO#F@!j^4P?(Eb$hw4L7a;Lh z&`K@*m2qc=|2VTZxs+*rRm?&^!Jw977cjTDVaNJdM0!cu+p}|oiW-y5f=iGA(wEo+ zDoe_De=?N{ex|u<-p?#M)$~aNw_BQ+{?ud(7!QnS{4k{}3wXM7R<_J)pGmIiXuOF4 zdW#0g1)meONj6H2I6TxZF{+sj?(8M1owgsA=$4LH#0pDCEYv{|3x_AV&p+HBe@iz8 zqRaaP@!P)*1F;4?#q|)6@`rsgofWE7lw8}v~`gWotJ(RDXs@- zTte>OcInD`rS!Oqq~H3%c9t%IU|Hn9W=21gCVekwI<=<#06k-A8PuIdW!IKoSO2YO z+|6rY$+IqjyZXCQ z(|0Ngn9a#qIsSSn3u^CTf${c((6GH_wOV*ZZnIP$UcXt0f81sPBJLlm z=8OfmI5)%fw0$)YbOC!J@4zhzuWW{6FLS;DrX5-0<|v6-7v6t@%T=Avn22w+FVvDw z5LUkaQ&`cu83oOU`l9@}OCw?CD*{&y>661Tdv$ADgm-7rr-)uh#dT)dM z&iebo3vaGyA_8cStZYC{Cm5va*ngWk3W6OkAq-3atn$SQEr9E@P%>`mJCN< z|GUX%555)e-mueDz#WQMayidMgp$=#6TfBgL-`^5X^9aMtiUbmXn(g_EUqZbq3fXV zpw-pp-jQxGdwvVw*zfII5|LJ<9)>X!WYD(E;DXyg+NXc z4as0#Zwb;*o<4i`@^3)%NPiULV3)h$6<);6O}Ufn9?nI|N~rjkN8#4BPRNE~?d>ow z?`cJ0`CHyz-A8qUvgqwjE%ozzuz%}V5BxvifHoIdby;G{DSyEoh}At|% zHE|iK;}2u6Og(>kJCv&V*h$=z?Z!PVYM;htL0g>(m6;SMu!)}<)MvbcZIaJKRLGx5 z8;YMfbu@9t(%1BQ%hGg%Fz$S;bJ0CdZ|J0EJOqfhg!k_bv?j%KW)eK zgmW+paYxj~Alu##Ww+?dg8J=|L!u4Oiad_qu1InRHd8bSYg6&vcJ0hvK@-}-g)#2i z&kf1yJAABQr-Ep8x_m+1M#7wnI4vFtoc3ilw~0=o3V#TxJ+T{PS`&_h-R2H9g%{<= zzhIqrG;ecE;#Ado;5)Z z5u`6Ev$1Z|Nwqa@bJMg?z&3QtATjNz*0Hf5UF0-93U)jqX7+tKY9_-eMmkQ>jYCFp zyu*W&gMagwH7;9wz5R{|sEyC4L5eZ~Dtu=50u^XPywbTRFo@!89h+*lPx`gxTWWJr3+*fcxggYcGKhnpEXj{H55-N}e!s zn^8HNbc#uIf$(_=;E}Qm*0SMN!VLItv^!(g0d)$CB!j&%U%}S!?y9DBq0Z7mpdo#kW`>9*9!7EThXC>g1=`AIIvmoukg>FjYoCR)(v+E?Yen( zSt3GwSN6n^slDFQx`y+U7ERo%R>kP?X@wF0=9%n46b_y&^W}Y26*YuYSrhAEAH9Ab z>DT@$$54TD>kj#AR%N{u{#RqCRaTd)YJZm1y{7D8&~~x_$>xK{tHth9dA!Ia+X4Hk zX_ocq-~dO~S3?`*0-Y#VEfyq>IJ)1>9!-f$QDcAWb5}h%}bPeUG;!|?qNY=QMViv zyfglq&$E|$7mCx*W=^Eb)I&7GoU{qN@!MKf60zZ-2SIObxi(@O(~;apYow#q4bqCvuw9L_p2FC%Xl8 z*8ZJ_j_Kfj6RHhv|#V7%H?Rhp@Rf~|Q?tFGYDfIyY<-~;B$?5rE zS)5yr51Dls6{Yyq=@ikHgo)X~#Yz{sIZY#rotDu3w(yu%-U z^@ZtP&B*Ev9@Vn-0Ze9wz?R*ZO?-2xhw)@U#jZCx2h)yumBZeX{)<`0eOrWDlE&--(p&sAC{9Neu^ou8({1lu47^(&T)8m)yF zkEG0`TeNC8O?vTwh1-J%TJ->buiFJZ zQNks%kn7#9rJea)d!vjCk7(Tu$S4KU)g0_09TrlK*h$?DwHX_#?SGurT##+st#i!A zm2ta_F3F*WSXY*z*Uw6dRK9Ttr?wve9qp7yrrx-KzdgO-+E z0P(fRm=phzv(yT(1%HAu(A5&bUz2jg*_kOi%NA!M2!r;h)}cU3bK0m6`#xXx(L6dY zSM?6V`B4-l7Zx}uQ^!>o&ucMed+M_G&g!;e%3@IiF>q~`0UhG@f5uDo5_0Vgs3%18 z*}2;7W@R^b7p-Jmg@TMywywY{D0VmKzale~4T{E_hBz;qx_|!x>GWB;a9c)w-yei@ z>`wdi_V3SLdVVJXZrhMWLC!X5Y+0fFD9afZD2CyqYDSwqF55e8i>1rvy@|ff7TJf? z;DVgs;r_Vg#vHvSle}e6K%3VuVL?&0%CDS+s)c2;zG+?}dmv?!j`E986kg^t)CV~Z zkgY(KknLqLR(}(a?pn@mT`fLQHxpMv}5+vK;V~!$+dpF+Dv}!8h!)#0R`AvXd79z-HqjKM;U1y>yiA3CSu2Y zL*Y*Vy0VQJQ5CWwV=%%rL{Vr5mq!~k0cS4yuQvc;9e-=|vzwxz#$<&=cIXzMjcaym z?ye&JE`>yNgd2NN|81v77!2DWfa^KRd-AsJEzR3mH)l{Bw{5Y}Rl{x11AuvJ(y?ex z$O$6c6u^y{Z&h48+uF=O4Nj-oGI)|Yu*ley9Jmv4V~ z`Sxu~&wux>a1Bj&%Wmxn&g)ZbBYPK!I74*~f9a zI*ov2e|AxpwQKr>InUE3?ebwD^NkRSPLiHX8eONiQ-1mD(|)j@4rW5b#a3$B4@fO0 zh|_K7jgFChunaN$Z&r;wOJ_|MvyhS~%F3VT?4)kN`b-~9GRiz|TEcJz&@yVO@NZm?bOx77JNaKH6lfgEn1aU<(I zcz;IZ*DE!ucKEe!E6Q5h34N2d-may>gJRIrs8Yhu`03(oOzY9kKHRNos-fCML~6CD zwn(6E5{Yc+eWnjbK9yta1ejTE7uVpo&>P<~NS*-b3knN4Yl5*%?=>be$Je9sxSTZ8 z(f#3CmC1COfYc_0gDIjh(A~o8wbx4c2 z#2~)qy?d4LdZXP28kK_BCFITSL`|bl=>?W1$*Q}8tl{}k*O8^Xqq!_+m?ehmjjq+v z$SqpP^_-^}p|DZh10J%AXdUVEm49k>b_k?u6)ux(ynK8$SY*X{b1`1-??>19S$H*B zP9HzSP{B*~;JT)it4TIRCO26|YcUi|+D~9&x|0>nv*eC2=5QXb#>2fN$wW8MM3qdY zagG1v$uQ0aFqRkT>>{+OHa_<_jp8`02Fq1_0U2?=pA-|BJB>zRZDj4E7k@@5QH#!= zz-dfUbPuUghWGBBNi;rLO}R3kpLr|^rBNXD^#XYSYD)pH1cv(%`l`Hx-=PCJ15FY) zuvQVHty#Q`=ZV&!S|k-Kl6`v>Zs6fzJQvCJIzCIT@ybQ_?0id(0Mzo7Pp0em3ScjG zzz}voNlUK=%_E*nqxgz{4u2!5$5)%cOT&jzC;ZIk_rUwKUJZ~q!}Zvk6ZrtcpXo^t zR!H2ke??Mli^<90+w6bBXaI<@F=1h-q@jLX)LxZ>cVsD@pQL!X6vrRRd>)=r_sQN6 zc2k)&P&TIY@<{@tD<2;YkIw`-Lem{E+bGlGJY1l^Q>dp#mZ1VUJAcQFqLIGNiep*S zDCyfmd`@R@nyP5*KOz?secGomdVt@`Kmc*3hk)UzqtPlXwvIKz6QtHS(VLA?1r zM+>V0E3pnYg`KYOwbH{<46O&Cc?7Q^*amN?=i7ygUc)-~g~}?AuKfh| z*^7txpAZQ&>1k~%o`2(erj##Wu4o@QW)<>v^x1dcedj(ZuaHqg*V&q^Zw&_tJ+!nf z7YpJkvh%zocYtIsBW=NSwO)312AuH*%I@B9FwMg+rWK@ zfgOqy22Tf*v*jeP_FGZG z?6_yt6;3SKMdRlFqOG!8DmHulqpJ2UVs>0 z&0zXnBNJi?`o_zz$s<^-cYV9v+6IAttNyPCin;sr_OkY!xb1EysK=ntS z@-WkU&wq7WKZ^UVD@u}<_cBKOI}L#ayul`R+UVnC1D}q8rqpfbw1Dj9tJMsC8*eg( zWzYa0t^Sgs4<^7Ms+Bc1sqVX5w@DRstE!@rv6%;qH|Kmt=`N*ED8GqcnSFABkRr{3O78F~@W3fsY6UDsn z>__}tc4jt&AlJwLHq9c;p^9wOL?XU1+}s2KfsT-w6$|WE{V);eoh5DhZJc1%5*V%x zMu$e|k!@`UaR)432!X*G0Zp#n=N^w}?%_{5(oG95_7wd;i#nOy9}eTM;D6u1{|=9a z!++`EGF@7eXQ`(^ahEBa*4 z3Z4JYE<7{E;kKDp7+)rWsBG*+aRE(X+lilj_)LG!bsSeGMi_j>dvU;U-*QAh@`K(Psa%%71EI z{<{j0Q8+XA5x%w?@enKqti!7yTv_tb_6#qqr%+v0HJB!Ub-F@iefHL%Yn$B4sC~3D z8S#Qhv2!ajoyiMDH#fyK;D2^byv6V)!jj*t-K!;kC+~#z> zcB|q>R7K1_D)w1JSYr9k$G`*!|pXv80fsU z``?nEjHEfc{CgvJ$aSfxn|pe!sxT3L;P>-ce6G6?CT@^4}T{rm9Nd* z(>eY}xgT;Bxf&+&75=B?Q>GPlA8_UDeTFd|-fOUYbDBNeQeJ-Erizw?Iptfivi)lC zTY`P>R0)p4ElQKy$m|vs^tzdKJo~FvQ-__mjF-)y8`INXB$hr{9Mv-#t(+9kTb-eS3n4aQ)W;(R? z0Bd~p)#>S1=~&qX@Q9VI&*1QA++i~SnfD)!yKHhG_u+%F-+lw~9(}D&ZbzRov)!r6 z^mY1m3nM7IronLiXDMBNpIx2dEm!vhioG6waV;~ogtsb@{KVH4Pk-7P?a8_;-GBJa zJUjQ)6dCLFpZ_C9F_3-BHd09kj6_cFsP5&!v=nfk_RuIkt;V|)GPGS<`bt9S$aq{( z=Hz#C8=yoHu_0}}-pxeER0@1x*?_H$#(K7pe1D<^cVMg!NXw+c}>7wi1^;ppB}N^DumCZ%J^EkJ+PJv0~`oT853iGQJhY?R&6^`!+r*fGnYLExwhc9EXK1^eWhqV|xwH(jXO zXPy3K9D=rrE}wD|LOHjsK6K_4EAhcgAn;zpO@9FA$bZ!WBwrRyY2QD5IWg8YE|Zh8 z_>PNfBSuXhJta+j>yd)n36KbeqS8RLyC5$q6rBt2G`@$k``P_<+_b`ii6)R7D4&s6 z{ny27pnrjvWU*q0Ul=Ic&ktz43C zVSld=PClkp5eEM)O8qyGc)fYHtg;!tLc~4P$o_BKmf8Hj$paLyGBR{ICvz_tKmdnN zk#L+KxDtq{uV*FfCCTBzu=~y9B$X}Fj*HFB^z`uX>S>Y{;oHul zE`pjCDM%6oaCz3FyC|VkfzDV-vypLTgS)qxc}?&*)=X_lmOV!F@FNQ#7IuaF!H%chXFg43*k%(>k^WTO*%CdtoIuj9)ZJ7dmC`Y{kk8+4;3xGn) zlqLZyxk6`86fU|l*2J?xq`ym`Cx61gy_f>sfE(|s)c})|9c{SS+uDAtEiY&+e)CE) zS21*xM8dKxyiAMq+>u9!G_N?v81MD3eLDA}Lw%hZ+0>UHGI0xFq-DNa*(94bW*>%7 zGVbrs5c!jMAhT2esg2vQw%#fJW;KB3Ta$e5R)ay0JsB{Wormu|jAAhpChOwJ` zB4TW_2=a<wrzoZO9YbdlQ5@hT=`_XwC%A$BkgI8ZaS9*SN5Og6jd0 z#2X5rO8z^mOKbfNibR!5+DSJz*Xy{Q%$iErWRlZ$VjK{w6G_b3VtdMZu#5Ayrvzbyg^EQR&|k8NO^dhS&FL0Fj2Lu%k>c|rU8MDnav4!oUTnKcXat9i ze0q-}3}^w2C2Nt*yMN-D?uT}t#6~TOUDb?Wu)*=2%3`@pUpda{AAU7&$8X`zgoNVB zXe7DzFRu*`&=@FTtbI>td4*8{eMgES+D%2P)Cl$&ilb0$XZ7G~api&I&%$QW(Kb_WkMKwmS{~_<2lXhl^eQV0r6Klag^yR7 z<~69PpvZ`Y6D9l1i3UVrS#5mB8C$s}W<6ys(<_Zm{D0f~7Uni`B+b84s-5mp5g z>|PJqwASs%SUDSh^jYrN+fyqPWw9jHm|}5RMO#{$5%+8Ehutr^eBcdKu}I0ji;JC! h8H*@95(yxYNF=_*x1fu+g0ca8GYH5EbBIR22LPEtH>Usq diff --git a/homeassistant/components/frontend/www_static/mdi.html.gz b/homeassistant/components/frontend/www_static/mdi.html.gz index d28209bbfee547ca69508030a228197455bcf095..3ab4238a3970e7a735be3af0c39e796a81174316 100644 GIT binary patch delta 27 jcmcb2iR<1aE-v|Q4vs9fz2QvEja;od8z3RwvNn~e$y 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 7ba8aeef59fa5c0c0add65af13b578335fc6fb6f..686df6e41eee4b0db912d665b4d4f7ffde18b357 100644 GIT binary patch delta 16 XcmX>va$ba8zMF$%b;zNO>>gYIFarfs delta 16 XcmX>va$ba8zMF$1+I+=Eb`LH9ETaU> 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 737bbbd3f1936b297e1aa77f5ca88035ac88f387..f2414ac39071ea1d135aff6c01e67cda414cc83a 100644 GIT binary patch delta 16 XcmbQkHHV8`zMF$%b;zNO?4qmyD24=~ delta 16 XcmbQkHHV8`zMF%iy>Q+}c2QOUCxirc 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 3f13ec3811f47ea5380abe5dc08ac91002edcd93..95cdd62d016a4626ae1fcbfd302c49869f387696 100644 GIT binary patch delta 16 XcmeAW>kwm?@8;lG9dc+RJ0mv$CtL)B delta 16 XcmeAW>kwm?@8;l$Hea!kosk;=Bm4vW 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 fce404f74bba0b9ec341befd96396ed32e299299..679cc353108e3b243417b5ab49e273dece2f4a24 100644 GIT binary patch delta 16 Xcmca2dPS67zMF$%b;zNO>}RQ+}_RUfNF%1Q~ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-iframe.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-iframe.html.gz index e48eabf9a6dbc025d1cf8e70d8d608eeab5dbe7d..7425bda4684a5e7da2584f901774c16091bcb1e9 100644 GIT binary patch delta 16 XcmbQtJeiqYzMF$%b;zNO>^+PCC!PfK delta 16 XcmbQtJeiqYzMF%iy>Q+}_8vw6CY%Jx diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-logbook.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-logbook.html.gz index 725c5f2b91d7ce18fa6e504a93e73998590d9d2a..124f8f5ace25a780a04951c8ebd77373627f2493 100644 GIT binary patch delta 16 XcmdmBxxtcMzMF$%b;zNO>?>seF+l~= delta 16 XcmdmBxxtcMzMF$1%Xj@o_LVXKF7X9- diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html index 2f73f5a782a..296b14bd858 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html @@ -1,4 +1,4 @@ - \ No newline at end of file +case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){"mouse"!==t.pointerType&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&o.DomEvent.preventDefault(t);for(var e=!1,i=0;i1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!(!t.shiftKey||1!==t.which&&1!==t.button)&&(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,(!0))},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return!((e&&e.animate)!==!0&&!this.getSize().contains(i))&&(this.panBy(i,e),!0)}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return!(i.animate!==!0&&!this.getSize().contains(o))&&(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0)},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a}),setTimeout(o.bind(this._onZoomTransitionEnd,this),250)},this)},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),o.Util.requestAnimFrame(function(){this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)},this))}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth);var i=this._map.getZoom();(i>this.options.maxZoom||i.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document)- \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz index 58dbc7d9e9f10cd7086eedcb1a3fba8159c36a89..97afe1f0e84702a80767e0e51d6a721f3b758e46 100644 GIT binary patch delta 35955 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 delta 35948 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 diff --git a/homeassistant/components/frontend/www_static/webcomponents-lite.min.js.gz b/homeassistant/components/frontend/www_static/webcomponents-lite.min.js.gz index 7975cba5e1c3877cc4baddd0a411a2d8461584b5..ce2c99213a8943d63a8a84561bb913bfd1d57f99 100644 GIT binary patch delta 16 XcmX?{a5#ZozMF$%b;zNO>^24fHu(kZ delta 16 XcmX?{a5#ZozMF%iy>Q+}b{hi#HTMO= From 78675ed3f8182610eb487f750208c2a2538ed042 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Sat, 27 Aug 2016 20:07:20 -0700 Subject: [PATCH 193/193] Version bump to 0.27.0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index dc6f7f18345..a43e4e58a1a 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """Constants used by Home Assistant components.""" -__version__ = '0.27.0.dev0' +__version__ = '0.27.0' REQUIRED_PYTHON_VER = (3, 4) PLATFORM_FORMAT = '{}.{}'

_+!)Y>83d# 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 HITQc@4%&EV From a12dadab5e0acbda500a85717add8a6b68e005a0 Mon Sep 17 00:00:00 2001 From: Henning Dickten Date: Sun, 21 Aug 2016 12:47:40 +0200 Subject: [PATCH 121/193] Update pymysensors version to 0.7.1 --- homeassistant/components/mysensors.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index 82deb67064b..d40806bdc31 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -29,7 +29,7 @@ DOMAIN = 'mysensors' DEPENDENCIES = [] REQUIREMENTS = [ 'https://github.com/theolind/pymysensors/archive/' - 'd59e2548f8378371f7fcb0805f7800796a6fa044.zip#pymysensors==0.7'] + '8ce98b7fb56f7921a808eb66845ce8b2c455c81e.zip#pymysensors==0.7.1'] _LOGGER = logging.getLogger(__name__) ATTR_NODE_ID = 'node_id' ATTR_CHILD_ID = 'child_id' diff --git a/requirements_all.txt b/requirements_all.txt index 52825484870..b71796e01e0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -185,7 +185,7 @@ https://github.com/robbiet480/pygtfs/archive/00546724e4bbcb3053110d844ca44e22462 https://github.com/sander76/powerviewApi/archive/master.zip#powerviewApi==0.2 # homeassistant.components.mysensors -https://github.com/theolind/pymysensors/archive/d59e2548f8378371f7fcb0805f7800796a6fa044.zip#pymysensors==0.7 +https://github.com/theolind/pymysensors/archive/8ce98b7fb56f7921a808eb66845ce8b2c455c81e.zip#pymysensors==0.7.1 # homeassistant.components.alarm_control_panel.simplisafe https://github.com/w1ll1am23/simplisafe-python/archive/586fede0e85fd69e56e516aaa8e97eb644ca8866.zip#simplisafe-python==0.0.1 From 635e5c8eba39611fc94f68c50ea8c08682e61ac8 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Sun, 21 Aug 2016 13:29:13 -0400 Subject: [PATCH 122/193] Add voluptuous to ecobee, speedtest.net, fast.com, actiontec, forecast.io (#2872) * add voluptuous * fixes for comments * str to cv.string --- .../components/device_tracker/actiontec.py | 255 +++++++++--------- homeassistant/components/ecobee.py | 13 +- homeassistant/components/sensor/fastdotcom.py | 27 +- homeassistant/components/sensor/forecast.py | 34 ++- homeassistant/components/sensor/speedtest.py | 27 +- 5 files changed, 201 insertions(+), 155 deletions(-) diff --git a/homeassistant/components/device_tracker/actiontec.py b/homeassistant/components/device_tracker/actiontec.py index 5de139b9e1f..a4804848f4a 100644 --- a/homeassistant/components/device_tracker/actiontec.py +++ b/homeassistant/components/device_tracker/actiontec.py @@ -1,126 +1,129 @@ -""" -Support for Actiontec MI424WR (Verizon FIOS) routers. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/device_tracker.actiontec/ -""" -import logging -import re -import telnetlib -import threading -from collections import namedtuple -from datetime import timedelta - -import homeassistant.util.dt as dt_util -from homeassistant.components.device_tracker import DOMAIN -from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.helpers import validate_config -from homeassistant.util import Throttle - -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - -_LOGGER = logging.getLogger(__name__) - -_LEASES_REGEX = re.compile( - r'(?P([0-9]{1,3}[\.]){3}[0-9]{1,3})' + - r'\smac:\s(?P([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))' + - r'\svalid\sfor:\s(?P(-?\d+))' + - r'\ssec') - - -# pylint: disable=unused-argument -def get_scanner(hass, config): - """Validate the configuration and return an Actiontec scanner.""" - if not validate_config(config, - {DOMAIN: [CONF_HOST, CONF_USERNAME, CONF_PASSWORD]}, - _LOGGER): - return None - scanner = ActiontecDeviceScanner(config[DOMAIN]) - return scanner if scanner.success_init else None - -Device = namedtuple("Device", ["mac", "ip", "last_update"]) - - -class ActiontecDeviceScanner(object): - """This class queries a an actiontec router for connected devices.""" - - def __init__(self, config): - """Initialize the scanner.""" - self.host = config[CONF_HOST] - self.username = config[CONF_USERNAME] - self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() - self.last_results = [] - data = self.get_actiontec_data() - self.success_init = data is not None - _LOGGER.info("actiontec scanner initialized") - - def scan_devices(self): - """Scan for new devices and return a list with found device IDs.""" - self._update_info() - return [client.mac for client in self.last_results] - - def get_device_name(self, device): - """Return the name of the given device or None if we don't know.""" - if not self.last_results: - return None - for client in self.last_results: - if client.mac == device: - return client.ip - return None - - @Throttle(MIN_TIME_BETWEEN_SCANS) - def _update_info(self): - """Ensure the information from the router is up to date. - - Return boolean if scanning successful. - """ - _LOGGER.info("Scanning") - if not self.success_init: - return False - - with self.lock: - now = dt_util.now() - actiontec_data = self.get_actiontec_data() - if not actiontec_data: - return False - self.last_results = [Device(data['mac'], name, now) - for name, data in actiontec_data.items() - if data['timevalid'] > -60] - _LOGGER.info("actiontec scan successful") - return True - - def get_actiontec_data(self): - """Retrieve data from Actiontec MI424WR and return parsed result.""" - try: - telnet = telnetlib.Telnet(self.host) - telnet.read_until(b'Username: ') - telnet.write((self.username + '\n').encode('ascii')) - telnet.read_until(b'Password: ') - telnet.write((self.password + '\n').encode('ascii')) - prompt = telnet.read_until( - b'Wireless Broadband Router> ').split(b'\n')[-1] - telnet.write('firewall mac_cache_dump\n'.encode('ascii')) - telnet.write('\n'.encode('ascii')) - telnet.read_until(prompt) - leases_result = telnet.read_until(prompt).split(b'\n')[1:-1] - telnet.write('exit\n'.encode('ascii')) - except EOFError: - _LOGGER.exception("Unexpected response from router") - return - except ConnectionRefusedError: - _LOGGER.exception("Connection refused by router," + - " is telnet enabled?") - return None - - devices = {} - for lease in leases_result: - match = _LEASES_REGEX.search(lease.decode('utf-8')) - if match is not None: - devices[match.group('ip')] = { - 'ip': match.group('ip'), - 'mac': match.group('mac').upper(), - 'timevalid': int(match.group('timevalid')) - } - return devices +""" +Support for Actiontec MI424WR (Verizon FIOS) routers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/device_tracker.actiontec/ +""" +import logging +import re +import telnetlib +import threading +from collections import namedtuple +from datetime import timedelta +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +import homeassistant.util.dt as dt_util +from homeassistant.components.device_tracker import (DOMAIN, PLATFORM_SCHEMA) +from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME +from homeassistant.util import Throttle + +# Return cached results if last scan was less then this time ago. +MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) + +_LOGGER = logging.getLogger(__name__) + +_LEASES_REGEX = re.compile( + r'(?P([0-9]{1,3}[\.]){3}[0-9]{1,3})' + + r'\smac:\s(?P([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))' + + r'\svalid\sfor:\s(?P(-?\d+))' + + r'\ssec') + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Required(CONF_USERNAME): cv.string +}) + + +# pylint: disable=unused-argument +def get_scanner(hass, config): + """Validate the configuration and return an Actiontec scanner.""" + scanner = ActiontecDeviceScanner(config[DOMAIN]) + return scanner if scanner.success_init else None + +Device = namedtuple("Device", ["mac", "ip", "last_update"]) + + +class ActiontecDeviceScanner(object): + """This class queries a an actiontec router for connected devices.""" + + def __init__(self, config): + """Initialize the scanner.""" + self.host = config[CONF_HOST] + self.username = config[CONF_USERNAME] + self.password = config[CONF_PASSWORD] + self.lock = threading.Lock() + self.last_results = [] + data = self.get_actiontec_data() + self.success_init = data is not None + _LOGGER.info("actiontec scanner initialized") + + def scan_devices(self): + """Scan for new devices and return a list with found device IDs.""" + self._update_info() + return [client.mac for client in self.last_results] + + def get_device_name(self, device): + """Return the name of the given device or None if we don't know.""" + if not self.last_results: + return None + for client in self.last_results: + if client.mac == device: + return client.ip + return None + + @Throttle(MIN_TIME_BETWEEN_SCANS) + def _update_info(self): + """Ensure the information from the router is up to date. + + Return boolean if scanning successful. + """ + _LOGGER.info("Scanning") + if not self.success_init: + return False + + with self.lock: + now = dt_util.now() + actiontec_data = self.get_actiontec_data() + if not actiontec_data: + return False + self.last_results = [Device(data['mac'], name, now) + for name, data in actiontec_data.items() + if data['timevalid'] > -60] + _LOGGER.info("actiontec scan successful") + return True + + def get_actiontec_data(self): + """Retrieve data from Actiontec MI424WR and return parsed result.""" + try: + telnet = telnetlib.Telnet(self.host) + telnet.read_until(b'Username: ') + telnet.write((self.username + '\n').encode('ascii')) + telnet.read_until(b'Password: ') + telnet.write((self.password + '\n').encode('ascii')) + prompt = telnet.read_until( + b'Wireless Broadband Router> ').split(b'\n')[-1] + telnet.write('firewall mac_cache_dump\n'.encode('ascii')) + telnet.write('\n'.encode('ascii')) + telnet.read_until(prompt) + leases_result = telnet.read_until(prompt).split(b'\n')[1:-1] + telnet.write('exit\n'.encode('ascii')) + except EOFError: + _LOGGER.exception("Unexpected response from router") + return + except ConnectionRefusedError: + _LOGGER.exception("Connection refused by router," + + " is telnet enabled?") + return None + + devices = {} + for lease in leases_result: + match = _LEASES_REGEX.search(lease.decode('utf-8')) + if match is not None: + devices[match.group('ip')] = { + 'ip': match.group('ip'), + 'mac': match.group('mac').upper(), + 'timevalid': int(match.group('timevalid')) + } + return devices diff --git a/homeassistant/components/ecobee.py b/homeassistant/components/ecobee.py index d684b903d0c..702c7fd6304 100644 --- a/homeassistant/components/ecobee.py +++ b/homeassistant/components/ecobee.py @@ -7,7 +7,9 @@ https://home-assistant.io/components/ecobee/ import logging import os from datetime import timedelta +import voluptuous as vol +import homeassistant.helpers.config_validation as cv from homeassistant.helpers import discovery from homeassistant.const import CONF_API_KEY from homeassistant.loader import get_component @@ -15,12 +17,19 @@ from homeassistant.util import Throttle DOMAIN = "ecobee" NETWORK = None -HOLD_TEMP = 'hold_temp' +CONF_HOLD_TEMP = 'hold_temp' REQUIREMENTS = [ 'https://github.com/nkgilley/python-ecobee-api/archive/' '4856a704670c53afe1882178a89c209b5f98533d.zip#python-ecobee==0.0.6'] +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_API_KEY): cv.string, + vol.Optional(CONF_HOLD_TEMP, default=False): cv.boolean + }) +}, extra=vol.ALLOW_EXTRA) + _LOGGER = logging.getLogger(__name__) ECOBEE_CONFIG_FILE = 'ecobee.conf' @@ -67,7 +76,7 @@ def setup_ecobee(hass, network, config): configurator = get_component('configurator') configurator.request_done(_CONFIGURING.pop('ecobee')) - hold_temp = config[DOMAIN].get(HOLD_TEMP, False) + hold_temp = config[DOMAIN].get(CONF_HOLD_TEMP) discovery.load_platform(hass, 'climate', DOMAIN, {'hold_temp': hold_temp}, config) diff --git a/homeassistant/components/sensor/fastdotcom.py b/homeassistant/components/sensor/fastdotcom.py index db68d505b14..95d91d42efc 100644 --- a/homeassistant/components/sensor/fastdotcom.py +++ b/homeassistant/components/sensor/fastdotcom.py @@ -5,10 +5,12 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.fastdotcom/ """ import logging +import voluptuous as vol import homeassistant.util.dt as dt_util +import homeassistant.helpers.config_validation as cv from homeassistant.components import recorder -from homeassistant.components.sensor import DOMAIN +from homeassistant.components.sensor import (DOMAIN, PLATFORM_SCHEMA) from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import track_time_change @@ -22,6 +24,17 @@ CONF_MINUTE = 'minute' CONF_HOUR = 'hour' CONF_DAY = 'day' +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_SECOND, default=[0]): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), + vol.Optional(CONF_MINUTE, default=[0]): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), + vol.Optional(CONF_HOUR): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 23))]), + vol.Optional(CONF_DAY): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(1, 31))]), +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Fast.com sensor.""" @@ -43,10 +56,10 @@ class SpeedtestSensor(Entity): def __init__(self, speedtest_data): """Initialize the sensor.""" - self._name = 'Fast.com Speedtest' + self._name = 'Fast.com Download' self.speedtest_client = speedtest_data self._state = None - self._unit_of_measurement = 'Mbps' + self._unit_of_measurement = 'Mbit/s' @property def name(self): @@ -94,10 +107,10 @@ class SpeedtestData(object): """Initialize the data object.""" self.data = None track_time_change(hass, self.update, - second=config.get(CONF_SECOND, 0), - minute=config.get(CONF_MINUTE, 0), - hour=config.get(CONF_HOUR, None), - day=config.get(CONF_DAY, None)) + second=config.get(CONF_SECOND), + minute=config.get(CONF_MINUTE), + hour=config.get(CONF_HOUR), + day=config.get(CONF_DAY)) def update(self, now): """Get the latest data from fast.com.""" diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index 0ab2301dbe2..4f3b2cd17c7 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -6,12 +6,14 @@ https://home-assistant.io/components/sensor.forecast/ """ import logging from datetime import timedelta +import voluptuous as vol from requests.exceptions import ConnectionError as ConnectError, \ HTTPError, Timeout -from homeassistant.components.sensor import DOMAIN -from homeassistant.const import CONF_API_KEY -from homeassistant.helpers import validate_config +import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_API_KEY, CONF_NAME, + CONF_MONITORED_CONDITIONS) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle @@ -56,6 +58,16 @@ SENSOR_TYPES = { 'mm', 'in', 'mm', 'mm', 'mm'], } DEFAULT_NAME = "Forecast.io" +CONF_UNITS = 'units' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_MONITORED_CONDITIONS): + vol.All(cv.ensure_list, [vol.In(list(SENSOR_TYPES))]), + vol.Required(CONF_API_KEY): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_UNITS): vol.In(['auto', 'si', 'us', 'ca', 'uk', 'uk2']) +}) + # Return cached results if last scan was less then this time ago. MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120) @@ -67,12 +79,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if None in (hass.config.latitude, hass.config.longitude): _LOGGER.error("Latitude or longitude not set in Home Assistant config") return False - elif not validate_config({DOMAIN: config}, - {DOMAIN: [CONF_API_KEY]}, _LOGGER): - return False - if 'units' in config: - units = config['units'] + if CONF_UNITS in config: + units = config[CONF_UNITS] elif hass.config.units.is_metric: units = 'si' else: @@ -89,15 +98,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(error) return False - name = config.get('name', DEFAULT_NAME) + name = config.get(CONF_NAME) # Initialize and add all of the sensors. sensors = [] - for variable in config['monitored_conditions']: - if variable in SENSOR_TYPES: - sensors.append(ForeCastSensor(forecast_data, variable, name)) - else: - _LOGGER.error('Sensor type: "%s" does not exist', variable) + for variable in config[CONF_MONITORED_CONDITIONS]: + sensors.append(ForeCastSensor(forecast_data, variable, name)) add_devices(sensors) diff --git a/homeassistant/components/sensor/speedtest.py b/homeassistant/components/sensor/speedtest.py index 1ce653f7ae6..86fd48e4d03 100644 --- a/homeassistant/components/sensor/speedtest.py +++ b/homeassistant/components/sensor/speedtest.py @@ -8,10 +8,13 @@ import logging import re import sys from subprocess import check_output, CalledProcessError +import voluptuous as vol import homeassistant.util.dt as dt_util +import homeassistant.helpers.config_validation as cv from homeassistant.components import recorder -from homeassistant.components.sensor import DOMAIN +from homeassistant.components.sensor import (DOMAIN, PLATFORM_SCHEMA) +from homeassistant.const import CONF_MONITORED_CONDITIONS from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import track_time_change @@ -22,7 +25,6 @@ _SPEEDTEST_REGEX = re.compile(r'Ping:\s(\d+\.\d+)\sms[\r\n]+' r'Download:\s(\d+\.\d+)\sMbit/s[\r\n]+' r'Upload:\s(\d+\.\d+)\sMbit/s[\r\n]+') -CONF_MONITORED_CONDITIONS = 'monitored_conditions' CONF_SECOND = 'second' CONF_MINUTE = 'minute' CONF_HOUR = 'hour' @@ -33,6 +35,19 @@ SENSOR_TYPES = { 'upload': ['Upload', 'Mbit/s'], } +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_MONITORED_CONDITIONS): + vol.All(cv.ensure_list, [vol.In(list(SENSOR_TYPES.keys()))]), + vol.Optional(CONF_SECOND, default=[0]): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), + vol.Optional(CONF_MINUTE, default=[0]): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 59))]), + vol.Optional(CONF_HOUR): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 23))]), + vol.Optional(CONF_DAY): + vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(1, 31))]), +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Speedtest sensor.""" @@ -117,10 +132,10 @@ class SpeedtestData(object): """Initialize the data object.""" self.data = None track_time_change(hass, self.update, - second=config.get(CONF_SECOND, 0), - minute=config.get(CONF_MINUTE, 0), - hour=config.get(CONF_HOUR, None), - day=config.get(CONF_DAY, None)) + second=config.get(CONF_SECOND), + minute=config.get(CONF_MINUTE), + hour=config.get(CONF_HOUR), + day=config.get(CONF_DAY)) def update(self, now): """Get the latest data from speedtest.net.""" From f802d6bfa343fc40139f2eececd432867fa2f6a5 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 21 Aug 2016 11:44:40 -0700 Subject: [PATCH 123/193] Update test packages (#2918) --- requirements_test.txt | 7 +++---- setup.cfg | 2 +- tests/components/test_http.py | 12 ++++++------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/requirements_test.txt b/requirements_test.txt index 233856e8363..a996ef411c3 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,11 +1,10 @@ -flake8>=2.6.0 +flake8>=3.0.4 pylint>=1.5.6 -astroid>=1.4.8 coveralls>=1.1 pytest>=2.9.2 -pytest-cov>=2.2.1 +pytest-cov>=2.3.1 pytest-timeout>=1.0.0 -pytest-capturelog>=0.7 +pytest-catchlog>=1.2.2 pydocstyle>=1.0.0 requests_mock>=1.0 mypy-lang>=0.4 diff --git a/setup.cfg b/setup.cfg index b11dfac0c42..98a4f54d55d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [wheel] universal = 1 -[pytest] +[tool:pytest] testpaths = tests norecursedirs = .git testing_config diff --git a/tests/components/test_http.py b/tests/components/test_http.py index 7a6d7af673f..ef491a91b36 100644 --- a/tests/components/test_http.py +++ b/tests/components/test_http.py @@ -75,8 +75,8 @@ class TestHttp: def test_access_with_password_in_header(self, caplog): """Test access with password in URL.""" # Hide logging from requests package that we use to test logging - caplog.setLevel(logging.WARNING, - logger='requests.packages.urllib3.connectionpool') + caplog.set_level(logging.WARNING, + logger='requests.packages.urllib3.connectionpool') req = requests.get( _url(const.URL_API), @@ -84,7 +84,7 @@ class TestHttp: assert req.status_code == 200 - logs = caplog.text() + logs = caplog.text # assert const.URL_API in logs assert API_PASSWORD not in logs @@ -99,15 +99,15 @@ class TestHttp: def test_access_with_password_in_url(self, caplog): """Test access with password in URL.""" # Hide logging from requests package that we use to test logging - caplog.setLevel(logging.WARNING, - logger='requests.packages.urllib3.connectionpool') + caplog.set_level(logging.WARNING, + logger='requests.packages.urllib3.connectionpool') req = requests.get(_url(const.URL_API), params={'api_password': API_PASSWORD}) assert req.status_code == 200 - logs = caplog.text() + logs = caplog.text # assert const.URL_API in logs assert API_PASSWORD not in logs From d70d1e13037880ad2504ff34f1685caf3cbadca9 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sun, 21 Aug 2016 14:54:28 -0400 Subject: [PATCH 124/193] Add support for notifying with Slack attachments. (#2914) * Add support for notifying with Slack messages. When creating notifications, this allows you to pass in `attachments` with the `data`. It's an array of attachments as defined in https://api.slack.com/docs/message-attachments When passing in attachments, message is still required, but it's okay to be a blank string. * Split over multiple lines * Make sure attachments gets assigned, even if there isn't attachment data --- homeassistant/components/notify/slack.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/notify/slack.py b/homeassistant/components/notify/slack.py index 99d0c4ef663..39ca0197d0f 100644 --- a/homeassistant/components/notify/slack.py +++ b/homeassistant/components/notify/slack.py @@ -51,7 +51,15 @@ class SlackNotificationService(BaseNotificationService): import slacker channel = kwargs.get('target') or self._default_channel + data = kwargs.get('data') + if data: + attachments = data.get('attachments') + else: + attachments = None + try: - self.slack.chat.post_message(channel, message, as_user=True) + self.slack.chat.post_message(channel, message, + as_user=True, + attachments=attachments) except slacker.Error: _LOGGER.exception("Could not send slack notification") From 2b4980ae5d43b75fffe2e4955639679d74aab66d Mon Sep 17 00:00:00 2001 From: Dan Ford Date: Sun, 21 Aug 2016 13:09:44 -0700 Subject: [PATCH 125/193] Add tplink Archer C7 device tracking support for 5Ghz networks --- .../components/device_tracker/tplink.py | 26 ++++--- .../components/device_tracker/test_tplink.py | 69 +++++++++++++++++++ 2 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 tests/components/device_tracker/test_tplink.py diff --git a/homeassistant/components/device_tracker/tplink.py b/homeassistant/components/device_tracker/tplink.py index 37d4d2b4471..17beab02532 100755 --- a/homeassistant/components/device_tracker/tplink.py +++ b/homeassistant/components/device_tracker/tplink.py @@ -313,19 +313,23 @@ class Tplink4DeviceScanner(TplinkDeviceScanner): _LOGGER.info("Loading wireless clients...") - url = 'http://{}/{}/userRpm/WlanStationRpm.htm' \ - .format(self.host, self.token) - referer = 'http://{}'.format(self.host) - cookie = 'Authorization=Basic {}'.format(self.credentials) + mac_results = [] - page = requests.get(url, headers={ - 'cookie': cookie, - 'referer': referer - }) - result = self.parse_macs.findall(page.text) + # Check both the 2.4GHz and 5GHz client list URLs + for clients_url in ('WlanStationRpm.htm', 'WlanStationRpm_5g.htm'): + url = 'http://{}/{}/userRpm/{}' \ + .format(self.host, self.token, clients_url) + referer = 'http://{}'.format(self.host) + cookie = 'Authorization=Basic {}'.format(self.credentials) - if not result: + page = requests.get(url, headers={ + 'cookie': cookie, + 'referer': referer + }) + mac_results.extend(self.parse_macs.findall(page.text)) + + if not mac_results: return False - self.last_results = [mac.replace("-", ":") for mac in result] + self.last_results = [mac.replace("-", ":") for mac in mac_results] return True diff --git a/tests/components/device_tracker/test_tplink.py b/tests/components/device_tracker/test_tplink.py new file mode 100644 index 00000000000..715d4f3ffde --- /dev/null +++ b/tests/components/device_tracker/test_tplink.py @@ -0,0 +1,69 @@ +"""The tests for the tplink device tracker platform.""" + +import os +import unittest + +from homeassistant.components import device_tracker +from homeassistant.components.device_tracker.tplink import Tplink4DeviceScanner +from homeassistant.const import (CONF_PLATFORM, CONF_PASSWORD, CONF_USERNAME, + CONF_HOST) +import requests_mock + +from tests.common import get_test_home_assistant + + +class TestTplink4DeviceScanner(unittest.TestCase): + """Tests for the Tplink4DeviceScanner class.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + def tearDown(self): # pylint: disable=invalid-name + """Stop everything that was started.""" + try: + os.remove(self.hass.config.path(device_tracker.YAML_DEVICES)) + except FileNotFoundError: + pass + + @requests_mock.mock() + def test_get_mac_addresses_from_both_bands(self, m): + """ + Test grabbing the mac addresses from both 2.4 and 5 GHz clients pages. + """ + conf_dict = { + CONF_PLATFORM: 'tplink', + CONF_HOST: 'fake_host', + CONF_USERNAME: 'fake_user', + CONF_PASSWORD: 'fake_pass' + } + + # Mock the token retrieval process + FAKE_TOKEN = 'fake_token' + fake_auth_token_response = 'window.parent.location.href = ' \ + '"https://a/{}/userRpm/Index.htm";'.format( + FAKE_TOKEN) + + m.get('http://{}/userRpm/LoginRpm.htm?Save=Save'.format( + conf_dict[CONF_HOST]), text=fake_auth_token_response) + + FAKE_MAC_1 = 'CA-FC-8A-C8-BB-53' + FAKE_MAC_2 = '6C-48-83-21-46-8D' + FAKE_MAC_3 = '77-98-75-65-B1-2B' + mac_response_2_4 = '{} {}'.format(FAKE_MAC_1, FAKE_MAC_2) + mac_response_5 = '{}'.format(FAKE_MAC_3) + + # Mock the 2.4 GHz clients page + m.get('http://{}/{}/userRpm/WlanStationRpm.htm'.format( + conf_dict[CONF_HOST], FAKE_TOKEN), text=mac_response_2_4) + + # Mock the 5 GHz clients page + m.get('http://{}/{}/userRpm/WlanStationRpm_5g.htm'.format( + conf_dict[CONF_HOST], FAKE_TOKEN), text=mac_response_5) + + tplink = Tplink4DeviceScanner(conf_dict) + + expected_mac_results = [mac.replace('-', ':') for mac in + [FAKE_MAC_1, FAKE_MAC_2, FAKE_MAC_3]] + + self.assertEquals(tplink.last_results, expected_mac_results) From 520d4d5dc04d07f092733287620e0dc544f56cf8 Mon Sep 17 00:00:00 2001 From: Jesse Newland Date: Sun, 21 Aug 2016 16:36:44 -0500 Subject: [PATCH 126/193] Add zwave.rename_node service (#2923) * Add zwave.rename_node service * Validate service data * Better schema --- homeassistant/components/services.yaml | 10 ++++++++++ homeassistant/components/zwave.py | 27 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/services.yaml b/homeassistant/components/services.yaml index 901a00a72ef..4cbf2a74867 100644 --- a/homeassistant/components/services.yaml +++ b/homeassistant/components/services.yaml @@ -100,3 +100,13 @@ zwave: test_network: description: This will send test to nodes in the zwave network. This will greatly slow down the zwave network while it is being processed. Refer to OZW.log for details. + + rename_node: + description: Set the name of a node. + fields: + entity_id: + description: Name(s) of entities to to rename + example: 'light.leviton_vrmx11lz_multilevel_scene_switch_level_40' + name: + description: New Name + example: 'kitchen' diff --git a/homeassistant/components/zwave.py b/homeassistant/components/zwave.py index 3e0db87664e..fa0cf410942 100644 --- a/homeassistant/components/zwave.py +++ b/homeassistant/components/zwave.py @@ -8,6 +8,7 @@ import logging import os.path import time from pprint import pprint +import voluptuous as vol from homeassistant.helpers import discovery from homeassistant.const import ( @@ -16,6 +17,8 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers.event import track_time_change from homeassistant.util import convert, slugify +import homeassistant.config as conf_util +import homeassistant.helpers.config_validation as cv DOMAIN = "zwave" REQUIREMENTS = ['pydispatcher==2.0.5'] @@ -40,6 +43,7 @@ SERVICE_SOFT_RESET = "soft_reset" SERVICE_TEST_NETWORK = "test_network" SERVICE_STOP_NETWORK = "stop_network" SERVICE_START_NETWORK = "start_network" +SERVICE_RENAME_NODE = "rename_node" EVENT_SCENE_ACTIVATED = "zwave.scene_activated" EVENT_NODE_EVENT = "zwave.node_event" @@ -187,10 +191,15 @@ DISCOVERY_COMPONENTS = [ ATTR_NODE_ID = "node_id" ATTR_VALUE_ID = "value_id" ATTR_OBJECT_ID = "object_id" - +ATTR_NAME = "name" ATTR_SCENE_ID = "scene_id" ATTR_BASIC_LEVEL = "basic_level" +RENAME_NODE_SCHEMA = vol.Schema({ + vol.Required(ATTR_ENTITY_ID): cv.entity_id, + vol.Required(ATTR_NAME): cv.string, +}) + NETWORK = None _LOGGER = logging.getLogger(__name__) @@ -272,6 +281,9 @@ def setup(hass, config): # pylint: disable=global-statement, import-error global NETWORK + descriptions = conf_util.load_yaml_config_file( + os.path.join(os.path.dirname(__file__), "services.yaml")) + try: import libopenzwave except ImportError: @@ -461,6 +473,16 @@ def setup(hass, config): NETWORK.stop() hass.bus.fire(EVENT_NETWORK_STOP) + def rename_node(service): + """Rename a node.""" + state = hass.states.get(service.data.get(ATTR_ENTITY_ID)) + node_id = state.attributes.get(ATTR_NODE_ID) + node = NETWORK.nodes[node_id] + name = service.data.get(ATTR_NAME) + node.name = name + _LOGGER.info( + "Renamed ZWave node %d to %s", node_id, name) + def start_zwave(_service_or_event): """Startup Z-Wave network.""" _LOGGER.info("Starting ZWave network.") @@ -505,6 +527,9 @@ def setup(hass, config): hass.services.register(DOMAIN, SERVICE_TEST_NETWORK, test_network) hass.services.register(DOMAIN, SERVICE_STOP_NETWORK, stop_zwave) hass.services.register(DOMAIN, SERVICE_START_NETWORK, start_zwave) + hass.services.register(DOMAIN, SERVICE_RENAME_NODE, rename_node, + descriptions[DOMAIN][SERVICE_RENAME_NODE], + schema=RENAME_NODE_SCHEMA) # Setup autoheal if autoheal: From 7598de90cb50fe734e408e2494d5a4dd8fe85ed4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 21 Aug 2016 16:01:24 -0700 Subject: [PATCH 127/193] Allow unregistering a push subscription (#2921) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow unregistering a push subscription * Update frontend * ps - HTML5 tests DRY 🍾 --- homeassistant/components/frontend/version.py | 4 +- .../components/frontend/www_static/core.js | 8 +- .../components/frontend/www_static/core.js.gz | Bin 31529 -> 32126 bytes .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 123558 -> 123252 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2274 -> 2279 bytes homeassistant/components/notify/html5.py | 24 +++ tests/components/notify/test_html5.py | 181 ++++++++++++++---- 10 files changed, 179 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index fbe60169862..8a5ffe63a79 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,8 +1,8 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "b4ee3a700ef5549a36b436611e27d3a9", - "frontend.html": "203371247fdba69b4d4d92fd707a459a", + "core.js": "7901b14f238956024a19139d6c479d68", + "frontend.html": "b33df7a012ea6d2aaf353c4466d6554a", "mdi.html": "710b84acc99b32514f52291aba9cd8e8", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index 4def07355e1..e336deae556 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&&"object"==typeof t&&"default"in t?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 De({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ce.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 Re({authToken:n,host:r})}function u(){return Le.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 Pe.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?Be({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||Be;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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return In.getInitialState()}function C(t,e){t.dispatch(gn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:In})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[Wn(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[yn.byId(t),Jn,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return ar(n)}function H(){return sr.getInitialState()}function P(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 fr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return hr.getInitialState()}function V(t,e){t.dispatch(or.SERVER_CONFIG_LOADED,e)}function q(t){rn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(or.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:sr,serverConfig:hr})}function Y(t,e){var n=e.pane;return n}function B(){return Ir.getInitialState()}function J(t,e){var n=e.panels;return Or(n)}function W(){return wr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Ar.getInitialState()}function Z(t,e){t.dispatch(mr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(mr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(mr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return kr.getInitialState()}function rt(t,e){t.dispatch(jr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(jr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return xr.getInitialState()}function st(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(cn.fromJSON)))})})}function ct(){return Fr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,Br(e.map(cn.fromJSON)))})})}function ht(){return Jr.getInitialState()}function lt(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(Qr,r)})}function pt(){return Zr.getInitialState()}function _t(t,e){t.dispatch(Hr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),rn(t,"GET",n).then(function(e){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Hr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_START,{date:e}),rn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Hr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ei);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:xr,entityHistory:Fr,isLoadingEntityHistory:Kr,recentEntityHistory:Jr,recentEntityHistoryUpdated:Zr})}function gt(t){t.registerStores({moreInfoEntityId:kr})}function mt(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;oQo}function ae(t){t.registerStores({currentLogbookDate:Uo,isLoadingLogbookEntries:Po,logbookEntries:Ko,logbookEntriesUpdated:Jo})}function se(t,e){return rn(t,"POST","template",{template:e})}function ce(t){return t.set("isListening",!0)}function fe(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 he(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 le(){return _u.getInitialState()}function pe(){return _u.getInitialState()}function _e(){return _u.getInitialState()}function de(t){return du[t.hassId]}function ve(t){var e=de(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(hu.VOICE_TRANSMITTING,{finalTranscript:n}),Zn.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(hu.VOICE_DONE)},function(){t.dispatch(hu.VOICE_ERROR)})}}function ye(t){var e=de(t);e&&(e.recognition.stop(),du[t.hassId]=!1)}function Se(t){ve(t),ye(t)}function ge(t){var e=Se.bind(null,t);e();var n=new webkitSpeechRecognition;du[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(hu.VOICE_START)},n.onerror=function(){return t.dispatch(hu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=de(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:L(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?H():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?H().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():P(t)}function R(t){return null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function L(t){return(null===t||void 0===t?H():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 H(){return Tn||(Tn=new M([]))}function P(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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?P(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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():He(t)?t:xe().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function He(t){return Me(t)&&m(t)}function Pe(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=Pe(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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=Ht;var Hn="@@__IMMUTABLE_MAP__@@",Pn=Ut.prototype;Pn[Hn]=!0,Pn[sn]=Pn.remove,Pn.removeIn=Pn.deleteIn,Pt.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 Pt(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=Pn.withMutations,Xn.asMutable=Pn.asMutable,Xn.asImmutable=Pn.asImmutable,Xn.wasAltered=Pn.wasAltered;var Qn;t(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),be=t(Ie),Oe=e(function(t){var e=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};t.exports=e}),we=t(Oe),Te=we({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Ae=be.Store,De=be.toImmutable,Ce=new Ae({getInitialState:function(){return De({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Te.VALIDATING_AUTH_TOKEN,n),this.on(Te.VALID_AUTH_TOKEN,r),this.on(Te.INVALID_AUTH_TOKEN,i)}}),ze=be.Store,Re=be.toImmutable,Le=new ze({getInitialState:function(){return Re({authToken:null,host:""})},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,o),this.on(Te.LOG_OUT,u)}}),Me=be.Store,je=new Me({getInitialState:function(){return!0},initialize:function(){this.on(Te.VALID_AUTH_TOKEN,a)}}),Ne=we({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),ke="object"==typeof window&&"EventSource"in window,Ue=be.Store,He=be.toImmutable,Pe=new Ue({getInitialState:function(){return He({isSupported:ke,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ne.STREAM_START,s),this.on(Ne.STREAM_STOP,c),this.on(Ne.STREAM_ERROR,f),this.on(Ne.LOG_OUT,h)}}),xe=we({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Ve=be.Store,qe=new Ve({getInitialState:function(){return!0},initialize:function(){this.on(xe.API_FETCH_ALL_START,function(){return!0}),this.on(xe.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(xe.API_FETCH_ALL_FAIL,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Fe=be.Store,Ge=new Fe({getInitialState:function(){return!1},initialize:function(){this.on(xe.SYNC_SCHEDULED,function(){return!0}),this.on(xe.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(xe.LOG_OUT,function(){return!1})}}),Ke=we({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}),Ye=be.Store,Be=be.toImmutable,Je=new Ye({getInitialState:function(){return Be({})},initialize:function(){var t=this;this.on(Ke.API_FETCH_SUCCESS,l),this.on(Ke.API_SAVE_SUCCESS,l),this.on(Ke.API_DELETE_SUCCESS,p),this.on(Ke.LOG_OUT,function(){return t.getInitialState()})}}),We=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c199&&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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return Dn.getInitialState()}function C(t,e){t.dispatch(wn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:Dn})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[er(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[bn.byId(t),tr,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return pr(n)}function P(){return _r.getInitialState()}function H(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 vr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return yr.getInitialState()}function V(t,e){t.dispatch(hr.SERVER_CONFIG_LOADED,e)}function q(t){fn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(hr.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:_r,serverConfig:yr})}function Y(t,e){var n=e.pane;return n}function B(){return Dr.getInitialState()}function J(t,e){var n=e.panels;return zr(n)}function W(){return Rr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Mr.getInitialState()}function Z(t,e){t.dispatch(Tr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(Tr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(Tr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return qr.getInitialState()}function rt(t,e){t.dispatch(xr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(xr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return Yr.getInitialState()}function st(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Jr({})):t.withMutations(function(t){r.forEach(function(e){return t.setIn([n,e[0].entity_id],Jr(e.map(dn.fromJSON)))})})}function ct(){return Wr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,$r(e.map(dn.fromJSON)))})})}function ht(){return ti.getInitialState()}function lt(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(ri,r)})}function pt(){return ii.getInitialState()}function _t(t,e){t.dispatch(Gr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),fn(t,"GET",n).then(function(e){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_START,{date:e}),fn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ai);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:Yr,entityHistory:Wr,isLoadingEntityHistory:Qr,recentEntityHistory:ti,recentEntityHistoryUpdated:ii})}function gt(t){t.registerStores({moreInfoEntityId:qr})}function mt(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;oru}function ae(t){t.registerStores({currentLogbookDate:Fo,isLoadingLogbookEntries:Ko,logbookEntries:Qo,logbookEntriesUpdated:tu})}function se(t){return t.set("active",!0)}function ce(t){return t.set("active",!1)}function fe(){return du.getInitialState()}function he(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",fn(t,"POST","notify.html5",{subscription:e,browser:n}).then(function(){return t.dispatch(lu.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),Mn.createNotification(t,n),!1})}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){return fn(t,"DELETE","notify.html5",{subscription:e}).then(function(){return e.unsubscribe()}).then(function(){return t.dispatch(lu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})}).then(function(){return!0})}).catch(function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Mn.createNotification(t,n),!1})}function pe(t){t.registerStores({pushNotifications:du})}function _e(t,e){return fn(t,"POST","template",{template:e})}function de(t){return t.set("isListening",!0)}function ve(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 ye(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 Se(){return Ru.getInitialState()}function ge(){return Ru.getInitialState()}function me(){return Ru.getInitialState()}function Ee(t){return Lu[t.hassId]}function Ie(t){var e=Ee(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Du.VOICE_TRANSMITTING,{finalTranscript:n}),ir.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(Du.VOICE_DONE)},function(){t.dispatch(Du.VOICE_ERROR)})}}function be(t){var e=Ee(t);e&&(e.recognition.stop(),Lu[t.hassId]=!1)}function Oe(t){Ie(t),be(t)}function we(t){var e=Oe.bind(null,t);e();var n=new webkitSpeechRecognition;Lu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Du.VOICE_START)},n.onerror=function(){return t.dispatch(Du.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ee(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:L(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 L(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 M([]))}function H(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){ +return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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 Me(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),Ce=t(De),ze=e(function(t){var e=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};t.exports=e}),Re=t(ze),Le=Re({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Me=Ce.Store,je=Ce.toImmutable,Ne=new Me({getInitialState:function(){return je({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)}}),ke=Ce.Store,Ue=Ce.toImmutable,Pe=new ke({getInitialState:function(){return Ue({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),He=Ce.Store,xe=new He({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),Ve=Re({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),qe="object"==typeof window&&"EventSource"in window,Fe=Ce.Store,Ge=Ce.toImmutable,Ke=new Fe({getInitialState:function(){return Ge({isSupported:qe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ve.STREAM_START,s),this.on(Ve.STREAM_STOP,c),this.on(Ve.STREAM_ERROR,f),this.on(Ve.LOG_OUT,h)}}),Ye=Re({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Be=Ce.Store,Je=new Be({getInitialState:function(){return!0},initialize:function(){this.on(Ye.API_FETCH_ALL_START,function(){return!0}),this.on(Ye.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(Ye.API_FETCH_ALL_FAIL,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),We=Ce.Store,Xe=new We({getInitialState:function(){return!1},initialize:function(){this.on(Ye.SYNC_SCHEDULED,function(){return!0}),this.on(Ye.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),Qe=Re({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}),Ze=Ce.Store,$e=Ce.toImmutable,tn=new Ze({getInitialState:function(){return $e({})},initialize:function(){var t=this;this.on(Qe.API_FETCH_SUCCESS,l),this.on(Qe.API_SAVE_SUCCESS,l),this.on(Qe.API_DELETE_SUCCESS,p),this.on(Qe.LOG_OUT,function(){return t.getInitialState()})}}),en=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),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 F0RRaD!)E{h literal 31529 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,t):(this._twiddle.textContent=this._twiddleContent++,this._callbacks.push(e),this._currVal++)},cancel:function(e){if(e<0)clearTimeout(~e);else{var t=e-this._lastVal;if(t>=0){if(!this._callbacks[t])throw"invalid async handle: "+e;this._callbacks[t]=null}}},_atEndOfMicrotask:function(){for(var e=this._callbacks.length,t=0;t \ No newline at end of file +this.currentTarget=t,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()},i=window.Element.prototype.animate;window.Element.prototype.animate=function(n,r){var o=i.call(this,n,r);o._cancelHandlers=[],o.oncancel=null;var a=o.cancel;o.cancel=function(){a.call(this);var i=new e(this,null,t()),n=this._cancelHandlers.concat(this.oncancel?[this.oncancel]:[]);setTimeout(function(){n.forEach(function(t){t.call(i.target,i)})},0)};var s=o.addEventListener;o.addEventListener=function(t,e){"function"==typeof e&&"cancel"==t?this._cancelHandlers.push(e):s.call(this,t,e)};var u=o.removeEventListener;return o.removeEventListener=function(t,e){if("cancel"==t){var i=this._cancelHandlers.indexOf(e);i>=0&&this._cancelHandlers.splice(i,1)}else u.call(this,t,e)},o}}}(),function(t){var e=document.documentElement,i=null,n=!1;try{var r=getComputedStyle(e).getPropertyValue("opacity"),o="0"==r?"1":"0";i=e.animate({opacity:[o,o]},{duration:1}),i.currentTime=0,n=getComputedStyle(e).getPropertyValue("opacity")==o}catch(t){}finally{i&&i.cancel()}if(!n){var a=window.Element.prototype.animate;window.Element.prototype.animate=function(e,i){return window.Symbol&&Symbol.iterator&&Array.prototype.from&&e[Symbol.iterator]&&(e=Array.from(e)),Array.isArray(e)||null===e||(e=t.convertToArrayForm(e)),a.call(this,e,i)}}}(c),!function(t,e,i){function n(t){var i=e.timeline;i.currentTime=t,i._discardAnimations(),0==i._animations.length?o=!1:requestAnimationFrame(n)}var r=window.requestAnimationFrame;window.requestAnimationFrame=function(t){return r(function(i){e.timeline._updateAnimationsPromises(),t(i),e.timeline._updateAnimationsPromises()})},e.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},e.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},_updateAnimationsPromises:function(){e.animationsWithPromises=e.animationsWithPromises.filter(function(t){return t._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(t){return"finished"!=t.playState&&"idle"!=t.playState})},_play:function(t){var i=new e.Animation(t,this);return this._animations.push(i),e.restartWebAnimationsNextTick(),i._updatePromises(),i._animation.play(),i._updatePromises(),i},play:function(t){return t&&t.remove(),this._play(t)}};var o=!1;e.restartWebAnimationsNextTick=function(){o||(o=!0,requestAnimationFrame(n))};var a=new e.AnimationTimeline;e.timeline=a;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return a}})}catch(t){}try{window.document.timeline=a}catch(t){}}(c,e,f),function(t,e,i){e.animationsWithPromises=[],e.Animation=function(e,i){if(this.id="",e&&e._id&&(this.id=e._id),this.effect=e,e&&(e._animation=this),!i)throw new Error("Animation with null timeline is not supported");this._timeline=i,this._sequenceNumber=t.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},e.Animation.prototype={_updatePromises:function(){var t=this._oldPlayState,e=this.playState;return this._readyPromise&&e!==t&&("idle"==e?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==t?this._resolveReadyPromise():"pending"==e&&(this._readyPromise=void 0)),this._finishedPromise&&e!==t&&("idle"==e?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==e?this._resolveFinishedPromise():"finished"==t&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var t,i,n,r,o=!!this._animation;o&&(t=this.playbackRate,i=this._paused,n=this.startTime,r=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=e.newUnderlyingAnimationForKeyframeEffect(this.effect),e.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=e.newUnderlyingAnimationForGroup(this.effect),e.bindAnimationForGroup(this)),this.effect&&this.effect._onsample&&e.bindAnimationForCustomEffect(this),o&&(1!=t&&(this.playbackRate=t),null!==n?this.startTime=n:null!==r?this.currentTime=r:null!==this._holdTime&&(this.currentTime=this._holdTime),i&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var t=this.effect._timing.delay;this._childAnimations.forEach(function(i){this._arrangeChildren(i,t),this.effect instanceof window.SequenceEffect&&(t+=e.groupChildDuration(i.effect))}.bind(this))}},_setExternalAnimation:function(t){if(this.effect&&this._isGroup)for(var e=0;e \ 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 85c93d71a4ccbb9b090dd983e6d6bdfa197f706c..20a48a1f014d0d43a1eb7c60b844615ac0be5471 100644 GIT binary patch delta 12115 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 BaykG2 literal 2274 zcmV<82p#tyiwFpiO}SSB19N3^c4=c}Uw3bEYh`jSYI6XkSow3?xE20a6i!zmYl^1wY%`Qq`u=h2-`>zg|LRUh%RNTz+@KH{Ojd8u+kk=iAjA-t9Xz zLI2<@ZaDsLS59Epe8XoC*Kx@=*Go8sJO7a_!M7{3W7>i4&LRaR7(jnFJN$4uoxT^} zK$;%C{*@P$P|eJII9z`!>k1>WlBRC98-~L@alQs4=dLs6%VOM_cOA^lqD;neZG+?A zEWpfbb?SV0|LL>i&w(pw+Ea_}Kl*3)#(7m&2C*D{MrWN;H7ud|HW@tqpv`gL$mJLXoIjBJwv+3EHGj@C@ zlTxN>!etavk}9sUTxN_hPLq(cOgra3eyE$yEHz&83d(k@;Bo{u=A%f;JSQCTkft)! zf+w7(nTn#AM_f?Rp@4dTQc$6yiiBB~$vgwWQW~n9=!7OBKCY*zbUlh!r!0n0 ztC&jQ9F$5mq?~Ux2`OVkv2&nMU-|BQ9ZE8F8JdFyGeH$)kMr(zFx2u^NqT$4xD2Q;$D(Kck=PQU%6n6s01{uoOiU zr)j1!j%Z#?Dd$`f5vI|PM7=3ybF-F($Z3)1not2UCvl_^eo6$oN-<*bk7T_CRjd|k zVH!vTF+ofTlL%pwr%6Zvn}AS&vVSD(Bg|GMZ`RVVPibsVm^*^&gs@a|K@u)<1$i71 zxht)(eS56=rF|G-Qv8m8gJm^CIWb`@j6{wQp+P(YidjO002UHLvgD|o0RO@LA(ne0 z6wgpAShqkBDKL&QWmrFZ5ETnPgBFRPQ5Oq@hF@S=UPE&sW@~GB6w{n2B1s-$+F*I6 zF-22Y6hcZk-<5U+Le`6AU19faM`dA<*o&$!0}*0>>24)2kNXIZQ4pxFz)=0#TdZuUN-&SUEF+TUXQokS}Tl&0yT`Bl|dOu@WUbf`KrQ5czx!#>G8^E^LjYpg8g_p4r` zJk&U-hC{g{2`45?>XmnU>&l=-rj_%P>Gtu3GjuErCs4^+!IzJ(Uu^>88t=rJI*+~K zp6AOwbBp!^`to&-p)3()P!I4av}*?ySdS%MZ|t*hvJaf`wwO$|qg`7s;IWa8uYK#L z1K&;y%hz2n)m}9JSfo%|kH~cMu#Oe+f)?i&<04Yt@%eN8&D60&s4hy>{Md&kz>%Z5 zzJFylubyG&f))qVv+&&OM%kmfzSTvwQPn@AX%F&e&f9s1L0={pJ9XmtI4rlH>rHaC z9U5;@+x~cUV1R|rOs#=F#~*U;SNDrTkYF~S^SJ_&_AnojQ8dF zo##zDd02PdT>i!;RfU*31<0e`oc0`ZiDBBu zvyb%V%yiVj$^U`-k;5K;6m9+#l=kem180Ax!EgQuP_is62jMR-7C(ThJ09)hgjP6z z|Mj!ewYH{@U(g?s)*xb~9PLc*{T_7TDJJqJX8JG+eHwKQw3=dBASv}T+2k3X>?%tz z(*xRaEqD0Gg!R(o6ltpyB8Nk#!kJ-a6J*~!;+fkM{Vkp(Z*5B` zZ`VhYi>tc%4h>TM?SfZ@wzBM*5R1k8>tAq2*n^~F$!&{~4_eG_%Q)(hZ|o7cfflJt zeJ#xV&*y2+G7sg?pyNTzFWJ3+q+i&Xt1fMgG?n}ORlO=z_3!6qV6lKfZ&M2cUE|sJ zr`8$RZZhahIvxD<{`o!@$X)9L`gXZX*W>xRT($E@%6ihD_7Pg_Sc!xJ9-OY!Cxd_E2C}({^V(&!OcPRG9UX0w|g?LX@ds~BZ zg+*LnIgj09byJI9O)yumBEkv(+h&xS@RJh{`%s09%#o3;LM&BO>F8RnTI>viYSSI7 wpj&gj3GUdKVJqQlr+V|*;T!kQg#+>1566>%z^}VF+ Date: Sun, 21 Aug 2016 16:58:42 -0700 Subject: [PATCH 128/193] Update frontend --- .../components/frontend/www_static/home-assistant-polymer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index c0c0b2c2f3c..87421f91363 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit c0c0b2c2f3ccfa6b04c6073c4e826ccae9baf8b6 +Subproject commit 87421f913635d32d3d116d9e26146e965b1e5e81 From 5d816b5eb5bd478d4e3da60b5b26e9c8b5309444 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 22 Aug 2016 08:20:31 +0200 Subject: [PATCH 129/193] Use voluptuous for OhmConnect (#2906) * Migrate to voluptuous * Remove string --- homeassistant/components/sensor/ohmconnect.py | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/sensor/ohmconnect.py b/homeassistant/components/sensor/ohmconnect.py index fcd50d8edc5..929fa607a4e 100644 --- a/homeassistant/components/sensor/ohmconnect.py +++ b/homeassistant/components/sensor/ohmconnect.py @@ -7,27 +7,37 @@ https://home-assistant.io/components/sensor.ohmconnect/ import logging from datetime import timedelta import xml.etree.ElementTree as ET -import requests +import requests +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME +import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) -# Return cached results if last scan was less then this time ago. +CONF_ID = 'id' + +DEFAULT_NAME = 'OhmConnect Status' + MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1) +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_ID): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the OhmConnect sensors.""" - ohmid = config.get("id") - if ohmid is None: - _LOGGER.error("You must provide your OhmConnect ID!") - return False + """Setup the OhmConnect sensor.""" + name = config.get(CONF_NAME) + ohmid = config.get(CONF_ID) - add_devices([OhmconnectSensor(config.get("name", "OhmConnect Status"), - ohmid)]) + add_devices([OhmconnectSensor(name, ohmid)]) class OhmconnectSensor(Entity): From 32318c6f1993a1381316eeae0392dfd7922b2a8d Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Mon, 22 Aug 2016 09:11:16 +0100 Subject: [PATCH 130/193] Add voluptuous validation to template sensor. (#2886) --- homeassistant/components/sensor/template.py | 32 +++++++++------------ tests/components/sensor/test_template.py | 22 ++++++-------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 668db816619..0462d664e26 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -5,8 +5,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.template/ """ import logging +import voluptuous as vol +import homeassistant.helpers.config_validation as cv -from homeassistant.components.sensor import ENTITY_ID_FORMAT +from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, ATTR_ENTITY_ID, MATCH_ALL) @@ -14,37 +16,31 @@ from homeassistant.exceptions import TemplateError from homeassistant.helpers.entity import Entity, generate_entity_id from homeassistant.helpers import template from homeassistant.helpers.event import track_state_change -from homeassistant.util import slugify _LOGGER = logging.getLogger(__name__) CONF_SENSORS = 'sensors' +SENSOR_SCHEMA = vol.Schema({ + vol.Required(CONF_VALUE_TEMPLATE): cv.template, + vol.Optional(ATTR_FRIENDLY_NAME): cv.string, + vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string, + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_SENSORS): vol.Schema({cv.slug: SENSOR_SCHEMA}), +}) + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the template sensors.""" sensors = [] - if config.get(CONF_SENSORS) is None: - _LOGGER.error("Missing configuration data for sensor platform") - return False for device, device_config in config[CONF_SENSORS].items(): - if device != slugify(device): - _LOGGER.error("Found invalid key for sensor.template: %s. " - "Use %s instead", device, slugify(device)) - continue - - if not isinstance(device_config, dict): - _LOGGER.error("Missing configuration data for sensor %s", device) - continue - friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT) state_template = device_config.get(CONF_VALUE_TEMPLATE) - if state_template is None: - _LOGGER.error( - "Missing %s for sensor %s", CONF_VALUE_TEMPLATE, device) - continue entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL) diff --git a/tests/components/sensor/test_template.py b/tests/components/sensor/test_template.py index 0170e6b3dfa..d85c9164851 100644 --- a/tests/components/sensor/test_template.py +++ b/tests/components/sensor/test_template.py @@ -1,5 +1,5 @@ """The test for the Template sensor platform.""" -import homeassistant.components.sensor as sensor +import homeassistant.bootstrap as bootstrap from tests.common import get_test_home_assistant @@ -17,7 +17,7 @@ class TestTemplateSensor: def test_template(self): """Test template.""" - assert sensor.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { @@ -39,7 +39,7 @@ class TestTemplateSensor: def test_template_syntax_error(self): """Test templating syntax error.""" - assert sensor.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { @@ -50,15 +50,11 @@ class TestTemplateSensor: } } }) - - self.hass.states.set('sensor.test_state', 'Works') - self.hass.pool.block_till_done() - state = self.hass.states.get('sensor.test_template_sensor') - assert state.state == 'unknown' + assert self.hass.states.all() == [] def test_template_attribute_missing(self): """Test missing attribute template.""" - assert sensor.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { @@ -75,7 +71,7 @@ class TestTemplateSensor: def test_invalid_name_does_not_create(self): """Test invalid name.""" - assert sensor.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { @@ -90,7 +86,7 @@ class TestTemplateSensor: def test_invalid_sensor_does_not_create(self): """Test invalid sensor.""" - assert sensor.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { @@ -102,7 +98,7 @@ class TestTemplateSensor: def test_no_sensors_does_not_create(self): """Test no sensors.""" - assert sensor.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template' } @@ -111,7 +107,7 @@ class TestTemplateSensor: def test_missing_template_does_not_create(self): """Test missing template.""" - assert sensor.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'sensor', { 'sensor': { 'platform': 'template', 'sensors': { From b6da4a53d5e6f3712b0187db163118b7777ae9b2 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 22 Aug 2016 11:28:58 +0200 Subject: [PATCH 131/193] Use voluptuous for dweet and arduino (#2926) * Migrate to voluptuous * Migrate to voluptuous * One import is enough --- homeassistant/components/arduino.py | 25 ++++++++++++++++--------- homeassistant/components/dweet.py | 22 ++++++++++------------ homeassistant/const.py | 7 +++++++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/arduino.py b/homeassistant/components/arduino.py index 0a981940842..85431eb2753 100644 --- a/homeassistant/components/arduino.py +++ b/homeassistant/components/arduino.py @@ -6,27 +6,34 @@ https://home-assistant.io/components/arduino/ """ import logging +import voluptuous as vol + from homeassistant.const import ( EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) -from homeassistant.helpers import validate_config +from homeassistant.const import CONF_PORT +import homeassistant.helpers.config_validation as cv -DOMAIN = "arduino" REQUIREMENTS = ['PyMata==2.12'] -BOARD = None + _LOGGER = logging.getLogger(__name__) +BOARD = None + +DOMAIN = 'arduino' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_PORT): cv.string, + }), +}) + def setup(hass, config): """Setup the Arduino component.""" - if not validate_config(config, - {DOMAIN: ['port']}, - _LOGGER): - return False - import serial global BOARD try: - BOARD = ArduinoBoard(config[DOMAIN]['port']) + BOARD = ArduinoBoard(config[DOMAIN][CONF_PORT]) except (serial.serialutil.SerialException, FileNotFoundError): _LOGGER.exception("Your port is not accessible.") return False diff --git a/homeassistant/components/dweet.py b/homeassistant/components/dweet.py index 49c1e74f232..9a17a7aeea3 100644 --- a/homeassistant/components/dweet.py +++ b/homeassistant/components/dweet.py @@ -6,40 +6,38 @@ https://home-assistant.io/components/dweet/ """ import logging from datetime import timedelta + import voluptuous as vol -from homeassistant.const import EVENT_STATE_CHANGED, STATE_UNKNOWN +from homeassistant.const import ( + CONF_NAME, CONF_WHITELIST, EVENT_STATE_CHANGED, STATE_UNKNOWN) import homeassistant.helpers.config_validation as cv from homeassistant.helpers import state as state_helper from homeassistant.util import Throttle +REQUIREMENTS = ['dweepy==0.2.0'] _LOGGER = logging.getLogger(__name__) -DOMAIN = "dweet" -DEPENDENCIES = [] - -REQUIREMENTS = ['dweepy==0.2.0'] - -CONF_NAME = 'name' -CONF_WHITELIST = 'whitelist' +DOMAIN = 'dweet' MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=1) CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_NAME): cv.string, - vol.Required(CONF_WHITELIST): cv.string, + vol.Required(CONF_WHITELIST, default=[]): + vol.All(cv.ensure_list, [cv.entity_id]), }), -}, extra=vol.ALLOW_EXTRA) +}) # pylint: disable=too-many-locals def setup(hass, config): """Setup the Dweet.io component.""" conf = config[DOMAIN] - name = conf[CONF_NAME] - whitelist = conf.get(CONF_WHITELIST, []) + name = conf.get(CONF_NAME) + whitelist = conf.get(CONF_WHITELIST) json_body = {} def dweet_event_listener(event): diff --git a/homeassistant/const.py b/homeassistant/const.py index 13733d24e75..4bf1785fe7b 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -25,6 +25,7 @@ CONF_ALIAS = 'alias' CONF_API_KEY = 'api_key' CONF_BEFORE = 'before' CONF_BELOW = 'below' +CONF_BLACKLIST = 'blacklist' CONF_CODE = 'code' CONF_CONDITION = 'condition' CONF_CUSTOMIZE = 'customize' @@ -51,19 +52,25 @@ CONF_PAYLOAD = 'payload' CONF_PENDING_TIME = 'pending_time' CONF_PLATFORM = 'platform' CONF_PORT = 'port' +CONF_PREFIX = 'prefix' CONF_RESOURCE = 'resource' CONF_RESOURCES = 'resources' CONF_SCAN_INTERVAL = 'scan_interval' CONF_SENSOR_CLASS = 'sensor_class' +CONF_SSL = 'ssl' CONF_STATE = 'state' CONF_TEMPERATURE_UNIT = 'temperature_unit' CONF_TIME_ZONE = 'time_zone' +CONF_TOKEN = 'token' CONF_TRIGGER_TIME = 'trigger_time' CONF_UNIT_OF_MEASUREMENT = 'unit_of_measurement' CONF_UNIT_SYSTEM = 'unit_system' +CONF_URL = 'url' CONF_USERNAME = 'username' CONF_VALUE_TEMPLATE = 'value_template' +CONF_VERIFY_SSL = 'verify_ssl' CONF_WEEKDAY = 'weekday' +CONF_WHITELIST = 'whitelist' CONF_ZONE = 'zone' # #### EVENTS #### From fb639e08d7dda6cf4502e9ecf5ae5449e3410586 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 22 Aug 2016 14:19:19 +0200 Subject: [PATCH 132/193] Fix schemas and update ordering (#2932) --- homeassistant/components/alexa.py | 12 ++++---- homeassistant/components/arduino.py | 2 +- homeassistant/components/configurator.py | 36 ++++++++++++------------ homeassistant/components/conversation.py | 14 ++++----- homeassistant/components/demo.py | 3 +- homeassistant/components/discovery.py | 6 ++-- homeassistant/components/downloader.py | 23 ++++++++------- homeassistant/components/dweet.py | 2 +- 8 files changed, 48 insertions(+), 50 deletions(-) diff --git a/homeassistant/components/alexa.py b/homeassistant/components/alexa.py index 3a41d51419b..969c20583ee 100644 --- a/homeassistant/components/alexa.py +++ b/homeassistant/components/alexa.py @@ -11,17 +11,17 @@ from homeassistant.const import HTTP_BAD_REQUEST from homeassistant.helpers import template, script from homeassistant.components.http import HomeAssistantView -DOMAIN = 'alexa' -DEPENDENCIES = ['http'] - _LOGGER = logging.getLogger(__name__) API_ENDPOINT = '/api/alexa' -CONF_INTENTS = 'intents' -CONF_CARD = 'card' -CONF_SPEECH = 'speech' CONF_ACTION = 'action' +CONF_CARD = 'card' +CONF_INTENTS = 'intents' +CONF_SPEECH = 'speech' + +DOMAIN = 'alexa' +DEPENDENCIES = ['http'] def setup(hass, config): diff --git a/homeassistant/components/arduino.py b/homeassistant/components/arduino.py index 85431eb2753..73bd7a51dad 100644 --- a/homeassistant/components/arduino.py +++ b/homeassistant/components/arduino.py @@ -25,7 +25,7 @@ CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_PORT): cv.string, }), -}) +}, extra=vol.ALLOW_EXTRA) def setup(hass, config): diff --git a/homeassistant/components/configurator.py b/homeassistant/components/configurator.py index b7c102a584c..9f5cb397587 100644 --- a/homeassistant/components/configurator.py +++ b/homeassistant/components/configurator.py @@ -11,26 +11,26 @@ import logging from homeassistant.const import EVENT_TIME_CHANGED, ATTR_FRIENDLY_NAME from homeassistant.helpers.entity import generate_entity_id -DOMAIN = "configurator" -ENTITY_ID_FORMAT = DOMAIN + ".{}" - -SERVICE_CONFIGURE = "configure" - -STATE_CONFIGURE = "configure" -STATE_CONFIGURED = "configured" - -ATTR_LINK_NAME = "link_name" -ATTR_LINK_URL = "link_url" -ATTR_CONFIGURE_ID = "configure_id" -ATTR_DESCRIPTION = "description" -ATTR_DESCRIPTION_IMAGE = "description_image" -ATTR_SUBMIT_CAPTION = "submit_caption" -ATTR_FIELDS = "fields" -ATTR_ERRORS = "errors" - -_REQUESTS = {} _INSTANCES = {} _LOGGER = logging.getLogger(__name__) +_REQUESTS = {} + +ATTR_CONFIGURE_ID = 'configure_id' +ATTR_DESCRIPTION = 'description' +ATTR_DESCRIPTION_IMAGE = 'description_image' +ATTR_ERRORS = 'errors' +ATTR_FIELDS = 'fields' +ATTR_LINK_NAME = 'link_name' +ATTR_LINK_URL = 'link_url' +ATTR_SUBMIT_CAPTION = 'submit_caption' + +DOMAIN = 'configurator' + +ENTITY_ID_FORMAT = DOMAIN + '.{}' + +SERVICE_CONFIGURE = 'configure' +STATE_CONFIGURE = 'configure' +STATE_CONFIGURED = 'configured' # pylint: disable=too-many-arguments diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index 6b580fa21fb..89cbd73b6ab 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -15,20 +15,20 @@ from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON) import homeassistant.helpers.config_validation as cv -DOMAIN = "conversation" +REQUIREMENTS = ['fuzzywuzzy==0.11.1'] -SERVICE_PROCESS = "process" +ATTR_TEXT = 'text' -ATTR_TEXT = "text" +DOMAIN = 'conversation' + +REGEX_TURN_COMMAND = re.compile(r'turn (?P(?: |\w)+) (?P\w+)') + +SERVICE_PROCESS = 'process' SERVICE_PROCESS_SCHEMA = vol.Schema({ vol.Required(ATTR_TEXT): vol.All(cv.string, vol.Lower), }) -REGEX_TURN_COMMAND = re.compile(r'turn (?P(?: |\w)+) (?P\w+)') - -REQUIREMENTS = ['fuzzywuzzy==0.11.1'] - def setup(hass, config): """Register the process service.""" diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index 863a2084892..5695bc5005a 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -11,9 +11,8 @@ import homeassistant.core as ha import homeassistant.loader as loader from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM -DOMAIN = "demo" - DEPENDENCIES = ['conversation', 'introduction', 'zone'] +DOMAIN = 'demo' COMPONENTS_WITH_DEMO_PLATFORM = [ 'alarm_control_panel', diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 6db4af66207..0ac40c00f90 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -12,13 +12,13 @@ import threading from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.helpers.discovery import load_platform, discover -DOMAIN = "discovery" REQUIREMENTS = ['netdisco==0.7.1'] -SCAN_INTERVAL = 300 # seconds +DOMAIN = 'discovery' -SERVICE_WEMO = 'belkin_wemo' +SCAN_INTERVAL = 300 # seconds SERVICE_NETGEAR = 'netgear_router' +SERVICE_WEMO = 'belkin_wemo' SERVICE_HANDLERS = { SERVICE_NETGEAR: ('device_tracker', None), diff --git a/homeassistant/components/downloader.py b/homeassistant/components/downloader.py index c639619d7a7..b752743d2d4 100644 --- a/homeassistant/components/downloader.py +++ b/homeassistant/components/downloader.py @@ -16,21 +16,20 @@ from homeassistant.helpers import validate_config import homeassistant.helpers.config_validation as cv from homeassistant.util import sanitize_filename -DOMAIN = "downloader" - -SERVICE_DOWNLOAD_FILE = "download_file" - -ATTR_URL = "url" -ATTR_SUBDIR = "subdir" - -SERVICE_DOWNLOAD_FILE_SCHEMA = vol.Schema({ - # pylint: disable=no-value-for-parameter - vol.Required(ATTR_URL): vol.Url(), - vol.Optional(ATTR_SUBDIR): cv.string, -}) +ATTR_SUBDIR = 'subdir' +ATTR_URL = 'url' CONF_DOWNLOAD_DIR = 'download_dir' +DOMAIN = 'downloader' + +SERVICE_DOWNLOAD_FILE = 'download_file' + +SERVICE_DOWNLOAD_FILE_SCHEMA = vol.Schema({ + vol.Required(ATTR_URL): cv.url, + vol.Optional(ATTR_SUBDIR): cv.string, +}) + # pylint: disable=too-many-branches def setup(hass, config): diff --git a/homeassistant/components/dweet.py b/homeassistant/components/dweet.py index 9a17a7aeea3..d56d9d2ef93 100644 --- a/homeassistant/components/dweet.py +++ b/homeassistant/components/dweet.py @@ -29,7 +29,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_WHITELIST, default=[]): vol.All(cv.ensure_list, [cv.entity_id]), }), -}) +}, extra=vol.ALLOW_EXTRA) # pylint: disable=too-many-locals From e5969f0733d409fa1a1d43c45b20f3a22abc061f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 22 Aug 2016 14:20:04 +0200 Subject: [PATCH 133/193] Clean-up (#2933) --- homeassistant/components/lock/demo.py | 10 +++++----- homeassistant/components/lock/mqtt.py | 10 +++++----- homeassistant/components/lock/vera.py | 11 +++++------ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/lock/demo.py b/homeassistant/components/lock/demo.py index 06366429e6c..55929227039 100644 --- a/homeassistant/components/lock/demo.py +++ b/homeassistant/components/lock/demo.py @@ -5,20 +5,20 @@ For more details about this platform, please refer to the documentation https://home-assistant.io/components/demo/ """ from homeassistant.components.lock import LockDevice -from homeassistant.const import STATE_LOCKED, STATE_UNLOCKED +from homeassistant.const import (STATE_LOCKED, STATE_UNLOCKED) # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): - """Setup the demo lock platform.""" - add_devices_callback([ +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Demo lock platform.""" + add_devices([ DemoLock('Front Door', STATE_LOCKED), DemoLock('Kitchen Door', STATE_UNLOCKED) ]) class DemoLock(LockDevice): - """Representation of a demo lock.""" + """Representation of a Demo lock.""" def __init__(self, name, state): """Initialize the lock.""" diff --git a/homeassistant/components/lock/mqtt.py b/homeassistant/components/lock/mqtt.py index b188de21edc..81ab179efd4 100644 --- a/homeassistant/components/lock/mqtt.py +++ b/homeassistant/components/lock/mqtt.py @@ -23,9 +23,9 @@ DEPENDENCIES = ['mqtt'] CONF_PAYLOAD_LOCK = 'payload_lock' CONF_PAYLOAD_UNLOCK = 'payload_unlock' -DEFAULT_NAME = "MQTT Lock" -DEFAULT_PAYLOAD_LOCK = "LOCK" -DEFAULT_PAYLOAD_UNLOCK = "UNLOCK" +DEFAULT_NAME = 'MQTT Lock' +DEFAULT_PAYLOAD_LOCK = 'LOCK' +DEFAULT_PAYLOAD_UNLOCK = 'UNLOCK' DEFAULT_OPTIMISTIC = False PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({ @@ -39,9 +39,9 @@ PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({ # pylint: disable=unused-argument -def setup_platform(hass, config, add_devices_callback, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the MQTT lock.""" - add_devices_callback([MqttLock( + add_devices([MqttLock( hass, config[CONF_NAME], config.get(CONF_STATE_TOPIC), diff --git a/homeassistant/components/lock/vera.py b/homeassistant/components/lock/vera.py index 6ac8fb2c315..0307bbf4312 100644 --- a/homeassistant/components/lock/vera.py +++ b/homeassistant/components/lock/vera.py @@ -7,19 +7,18 @@ https://home-assistant.io/components/lock.vera/ import logging from homeassistant.components.lock import LockDevice -from homeassistant.const import ( - STATE_LOCKED, STATE_UNLOCKED) +from homeassistant.const import (STATE_LOCKED, STATE_UNLOCKED) from homeassistant.components.vera import ( VeraDevice, VERA_DEVICES, VERA_CONTROLLER) -DEPENDENCIES = ['vera'] - _LOGGER = logging.getLogger(__name__) +DEPENDENCIES = ['vera'] -def setup_platform(hass, config, add_devices_callback, discovery_info=None): + +def setup_platform(hass, config, add_devices, discovery_info=None): """Find and return Vera locks.""" - add_devices_callback( + add_devices( VeraLock(device, VERA_CONTROLLER) for device in VERA_DEVICES['lock']) From eac67fd97134ab7d0c27e77d9742568b8194df0c Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Mon, 22 Aug 2016 23:05:45 +0100 Subject: [PATCH 134/193] Add voluptuous to template switch (#2940) * Add voluptuous to template switch / revise tests. --- homeassistant/components/switch/template.py | 47 +++++++++------------ tests/components/switch/test_template.py | 39 ++++++++--------- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/homeassistant/components/switch/template.py b/homeassistant/components/switch/template.py index ebb3cb42258..274ff992088 100644 --- a/homeassistant/components/switch/template.py +++ b/homeassistant/components/switch/template.py @@ -5,8 +5,11 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.template/ """ import logging +import voluptuous as vol +import homeassistant.helpers.config_validation as cv -from homeassistant.components.switch import ENTITY_ID_FORMAT, SwitchDevice +from homeassistant.components.switch import ( + ENTITY_ID_FORMAT, SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import ( ATTR_FRIENDLY_NAME, CONF_VALUE_TEMPLATE, STATE_OFF, STATE_ON, ATTR_ENTITY_ID, MATCH_ALL) @@ -15,7 +18,6 @@ from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers.script import Script from homeassistant.helpers import template from homeassistant.helpers.event import track_state_change -from homeassistant.util import slugify CONF_SWITCHES = 'switches' @@ -25,40 +27,29 @@ OFF_ACTION = 'turn_off' _LOGGER = logging.getLogger(__name__) _VALID_STATES = [STATE_ON, STATE_OFF, 'true', 'false'] +SWITCH_SCHEMA = vol.Schema({ + vol.Required(CONF_VALUE_TEMPLATE): cv.template, + vol.Required(ON_ACTION): cv.SCRIPT_SCHEMA, + vol.Required(OFF_ACTION): cv.SCRIPT_SCHEMA, + vol.Optional(ATTR_FRIENDLY_NAME): cv.string, + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}), +}) + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Template switch.""" switches = [] - if config.get(CONF_SWITCHES) is None: - _LOGGER.error("Missing configuration data for switch platform") - return False for device, device_config in config[CONF_SWITCHES].items(): - - if device != slugify(device): - _LOGGER.error("Found invalid key for switch.template: %s. " - "Use %s instead", device, slugify(device)) - continue - - if not isinstance(device_config, dict): - _LOGGER.error("Missing configuration data for switch %s", device) - continue - friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) - state_template = device_config.get(CONF_VALUE_TEMPLATE) - on_action = device_config.get(ON_ACTION) - off_action = device_config.get(OFF_ACTION) - if state_template is None: - _LOGGER.error( - "Missing %s for switch %s", CONF_VALUE_TEMPLATE, device) - continue - - if on_action is None or off_action is None: - _LOGGER.error( - "Missing action for switch %s", device) - continue - + state_template = device_config[CONF_VALUE_TEMPLATE] + on_action = device_config[ON_ACTION] + off_action = device_config[OFF_ACTION] entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL) switches.append( diff --git a/tests/components/switch/test_template.py b/tests/components/switch/test_template.py index 1b8d6cf5ab9..2d8cf636217 100644 --- a/tests/components/switch/test_template.py +++ b/tests/components/switch/test_template.py @@ -1,6 +1,6 @@ """The tests for the Template switch platform.""" +import homeassistant.bootstrap as bootstrap import homeassistant.components as core -import homeassistant.components.switch as switch from homeassistant.const import ( STATE_ON, @@ -18,6 +18,7 @@ class TestTemplateSwitch: self.calls = [] def record_call(service): + """Track function calls..""" self.calls.append(service) self.hass.services.register('test', 'automation', record_call) @@ -28,7 +29,7 @@ class TestTemplateSwitch: def test_template_state_text(self): """"Test the state text of a template.""" - assert switch.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -62,7 +63,7 @@ class TestTemplateSwitch: def test_template_state_boolean_on(self): """Test the setting of the state with boolean on.""" - assert switch.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -87,7 +88,7 @@ class TestTemplateSwitch: def test_template_state_boolean_off(self): """Test the setting of the state with off.""" - assert switch.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -112,7 +113,7 @@ class TestTemplateSwitch: def test_template_syntax_error(self): """Test templating syntax error.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -131,15 +132,11 @@ class TestTemplateSwitch: } } }) - - state = self.hass.states.set('switch.test_state', STATE_ON) - self.hass.pool.block_till_done() - state = self.hass.states.get('switch.test_template_switch') - assert state.state == 'unavailable' + assert self.hass.states.all() == [] def test_invalid_name_does_not_create(self): """Test invalid name.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -161,8 +158,8 @@ class TestTemplateSwitch: assert self.hass.states.all() == [] def test_invalid_switch_does_not_create(self): - """Test invalid name.""" - assert switch.setup(self.hass, { + """Test invalid switch.""" + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -174,7 +171,7 @@ class TestTemplateSwitch: def test_no_switches_does_not_create(self): """Test if there are no switches no creation.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template' } @@ -183,7 +180,7 @@ class TestTemplateSwitch: def test_missing_template_does_not_create(self): """Test missing template.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -206,7 +203,7 @@ class TestTemplateSwitch: def test_missing_on_does_not_create(self): """Test missing on.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -229,7 +226,7 @@ class TestTemplateSwitch: def test_missing_off_does_not_create(self): """Test missing off.""" - assert switch.setup(self.hass, { + assert not bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -252,7 +249,7 @@ class TestTemplateSwitch: def test_on_action(self): """Test on action.""" - assert switch.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -279,11 +276,11 @@ class TestTemplateSwitch: core.switch.turn_on(self.hass, 'switch.test_template_switch') self.hass.pool.block_till_done() - assert 1 == len(self.calls) + assert len(self.calls) == 1 def test_off_action(self): """Test off action.""" - assert switch.setup(self.hass, { + assert bootstrap.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'template', 'switches': { @@ -311,4 +308,4 @@ class TestTemplateSwitch: core.switch.turn_off(self.hass, 'switch.test_template_switch') self.hass.pool.block_till_done() - assert 1 == len(self.calls) + assert len(self.calls) == 1 From 9fcfc213c7207029389139cc3a4140aed76b5575 Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Tue, 23 Aug 2016 04:50:05 +0100 Subject: [PATCH 135/193] Bump pywemo. (#2944) --- homeassistant/components/wemo.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/wemo.py b/homeassistant/components/wemo.py index 5fe124aaf45..29e6d53cd2c 100644 --- a/homeassistant/components/wemo.py +++ b/homeassistant/components/wemo.py @@ -14,7 +14,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.const import EVENT_HOMEASSISTANT_STOP -REQUIREMENTS = ['pywemo==0.4.5'] +REQUIREMENTS = ['pywemo==0.4.6'] DOMAIN = 'wemo' diff --git a/requirements_all.txt b/requirements_all.txt index 4345a815728..a04e7e986c3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -391,7 +391,7 @@ pyuserinput==0.1.9 pyvera==0.2.15 # homeassistant.components.wemo -pywemo==0.4.5 +pywemo==0.4.6 # homeassistant.components.climate.radiotherm # homeassistant.components.thermostat.radiotherm From dfca2476bd0de05cc4f4d23546279891f236f3bc Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Tue, 23 Aug 2016 04:51:17 +0100 Subject: [PATCH 136/193] Add voluptuous to efergy. (#2943) --- homeassistant/components/sensor/efergy.py | 60 +++++++++++++++-------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sensor/efergy.py b/homeassistant/components/sensor/efergy.py index 5650214da27..3a1bcfbf5a4 100644 --- a/homeassistant/components/sensor/efergy.py +++ b/homeassistant/components/sensor/efergy.py @@ -5,40 +5,60 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.efergy/ """ import logging +import voluptuous as vol from requests import RequestException, get +import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) _RESOURCE = 'https://engage.efergy.com/mobile_proxy/' + +CONF_APPTOKEN = 'app_token' +CONF_UTC_OFFSET = 'utc_offset' +CONF_MONITORED_VARIABLES = 'monitored_variables' +CONF_SENSOR_TYPE = 'type' + +CONF_CURRENCY = 'currency' +CONF_PERIOD = 'period' + +CONF_INSTANT = 'instant_readings' +CONF_BUDGET = 'budget' +CONF_COST = 'cost' + SENSOR_TYPES = { - 'instant_readings': ['Energy Usage', 'kW'], - 'budget': ['Energy Budget', None], - 'cost': ['Energy Cost', None], + CONF_INSTANT: ['Energy Usage', 'kW'], + CONF_BUDGET: ['Energy Budget', None], + CONF_COST: ['Energy Cost', None], } +TYPES_SCHEMA = vol.In( + [CONF_INSTANT, CONF_BUDGET, CONF_COST]) + +SENSORS_SCHEMA = vol.Schema({ + vol.Required(CONF_SENSOR_TYPE): TYPES_SCHEMA, + vol.Optional(CONF_CURRENCY, default=''): cv.string, + vol.Optional(CONF_PERIOD, default='year'): cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_APPTOKEN): cv.string, + vol.Optional(CONF_UTC_OFFSET): cv.string, + vol.Required(CONF_MONITORED_VARIABLES): [SENSORS_SCHEMA] +}) + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Efergy sensor.""" - app_token = config.get("app_token") - if not app_token: - _LOGGER.error( - "Configuration Error" - "Please make sure you have configured your app token") - return None - utc_offset = str(config.get("utc_offset")) + app_token = config.get(CONF_APPTOKEN) + utc_offset = str(config.get(CONF_UTC_OFFSET)) dev = [] - for variable in config['monitored_variables']: - if 'period' not in variable: - variable['period'] = '' - if 'currency' not in variable: - variable['currency'] = '' - if variable['type'] not in SENSOR_TYPES: - _LOGGER.error('Sensor type: "%s" does not exist', variable) - else: - dev.append(EfergySensor(variable['type'], app_token, utc_offset, - variable['period'], variable['currency'])) + for variable in config[CONF_MONITORED_VARIABLES]: + dev.append(EfergySensor( + variable[CONF_SENSOR_TYPE], app_token, utc_offset, + variable[CONF_PERIOD], variable[CONF_CURRENCY])) add_devices(dev) From 0def8422314d206e7497749e0adcf5c51faf0e2a Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Tue, 23 Aug 2016 05:52:31 +0200 Subject: [PATCH 137/193] Quick lint script for changed files (#2941) --- script/lint | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/script/lint b/script/lint index 4a517ef7494..ea8d84e7b84 100755 --- a/script/lint +++ b/script/lint @@ -3,4 +3,21 @@ # NOTE: all testing is now driven through tox. The tox command below # performs roughly what this test did in the past. -tox -e lint +if [ "$1" == "--changed" ]; then + export files=`git diff upstream/dev --name-only | grep -v requirements_all.txt` + echo "=================================================" + echo "FILES CHANGED (git diff upstream/dev --name-only)" + echo "=================================================" + echo $files + echo "================" + echo "LINT with flake8" + echo "================" + flake8 --doctests $files + echo "================" + echo "LINT with pylint" + echo "================" + pylint $files + echo +else + tox -e lint +fi From f00cdc50df8ee542f92fcbd6a9a32353e60178df Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Tue, 23 Aug 2016 00:31:17 -0400 Subject: [PATCH 138/193] Updated python-wink version to fix color/temp detection (#2935) --- homeassistant/components/binary_sensor/wink.py | 2 +- homeassistant/components/garage_door/wink.py | 2 +- homeassistant/components/light/wink.py | 2 +- homeassistant/components/lock/wink.py | 2 +- homeassistant/components/rollershutter/wink.py | 2 +- homeassistant/components/sensor/wink.py | 2 +- homeassistant/components/switch/wink.py | 2 +- homeassistant/components/wink.py | 2 +- requirements_all.txt | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/binary_sensor/wink.py b/homeassistant/components/binary_sensor/wink.py index 0ab8d812819..9ba717782e9 100644 --- a/homeassistant/components/binary_sensor/wink.py +++ b/homeassistant/components/binary_sensor/wink.py @@ -13,7 +13,7 @@ from homeassistant.const import CONF_ACCESS_TOKEN from homeassistant.helpers.entity import Entity from homeassistant.loader import get_component -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] # These are the available sensors mapped to binary_sensor class SENSOR_TYPES = { diff --git a/homeassistant/components/garage_door/wink.py b/homeassistant/components/garage_door/wink.py index 68ba1ae709f..c59d48d48bd 100644 --- a/homeassistant/components/garage_door/wink.py +++ b/homeassistant/components/garage_door/wink.py @@ -10,7 +10,7 @@ from homeassistant.components.garage_door import GarageDoorDevice from homeassistant.components.wink import WinkDevice from homeassistant.const import CONF_ACCESS_TOKEN -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/light/wink.py b/homeassistant/components/light/wink.py index 39c7e9f1ae6..957c3a4e116 100644 --- a/homeassistant/components/light/wink.py +++ b/homeassistant/components/light/wink.py @@ -15,7 +15,7 @@ from homeassistant.util import color as color_util from homeassistant.util.color import \ color_temperature_mired_to_kelvin as mired_to_kelvin -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] SUPPORT_WINK = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_RGB_COLOR diff --git a/homeassistant/components/lock/wink.py b/homeassistant/components/lock/wink.py index c85655cbf35..1a09414f8c3 100644 --- a/homeassistant/components/lock/wink.py +++ b/homeassistant/components/lock/wink.py @@ -10,7 +10,7 @@ from homeassistant.components.lock import LockDevice from homeassistant.components.wink import WinkDevice from homeassistant.const import CONF_ACCESS_TOKEN -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/rollershutter/wink.py b/homeassistant/components/rollershutter/wink.py index e18a75082a7..18ed193060b 100644 --- a/homeassistant/components/rollershutter/wink.py +++ b/homeassistant/components/rollershutter/wink.py @@ -10,7 +10,7 @@ from homeassistant.components.rollershutter import RollershutterDevice from homeassistant.components.wink import WinkDevice from homeassistant.const import CONF_ACCESS_TOKEN -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/sensor/wink.py b/homeassistant/components/sensor/wink.py index 4f39bd9f2ff..ddc160c5064 100644 --- a/homeassistant/components/sensor/wink.py +++ b/homeassistant/components/sensor/wink.py @@ -12,7 +12,7 @@ from homeassistant.helpers.entity import Entity from homeassistant.components.wink import WinkDevice from homeassistant.loader import get_component -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] SENSOR_TYPES = ['temperature', 'humidity'] diff --git a/homeassistant/components/switch/wink.py b/homeassistant/components/switch/wink.py index 1feb8e584bb..3a0cd1b7736 100644 --- a/homeassistant/components/switch/wink.py +++ b/homeassistant/components/switch/wink.py @@ -10,7 +10,7 @@ from homeassistant.components.wink import WinkDevice from homeassistant.const import CONF_ACCESS_TOKEN from homeassistant.helpers.entity import ToggleEntity -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] def setup_platform(hass, config, add_devices, discovery_info=None): diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 4a45cd8576f..96f40c8d1f7 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -12,7 +12,7 @@ from homeassistant.const import CONF_ACCESS_TOKEN, ATTR_BATTERY_LEVEL from homeassistant.helpers.entity import Entity DOMAIN = "wink" -REQUIREMENTS = ['python-wink==0.7.11', 'pubnub==3.8.2'] +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] SUBSCRIPTION_HANDLER = None CHANNELS = [] diff --git a/requirements_all.txt b/requirements_all.txt index a04e7e986c3..6e108ce3c01 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -382,7 +382,7 @@ python-twitch==1.3.0 # homeassistant.components.rollershutter.wink # homeassistant.components.sensor.wink # homeassistant.components.switch.wink -python-wink==0.7.11 +python-wink==0.7.13 # homeassistant.components.keyboard pyuserinput==0.1.9 From 14b034f4526760260f8cdd42e77f87491e8918c7 Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Tue, 23 Aug 2016 06:42:05 +0200 Subject: [PATCH 139/193] Check config script (#2657) * Add check_config, yaml linting script * WIP: Start reusing some bootstrap methods for validation * Start outputs * Secrets, files and failed config * requirements_all * Fixes * formatting * Fix unit test after formatting --- homeassistant/bootstrap.py | 12 +- homeassistant/scripts/check_config.py | 261 ++++++++++++++++++++++++++ homeassistant/util/yaml.py | 27 ++- requirements_all.txt | 7 + script/gen_requirements_all.py | 5 +- tests/common.py | 48 ++++- tests/scripts/test_check_config.py | 126 +++++++++++++ 7 files changed, 458 insertions(+), 28 deletions(-) create mode 100644 homeassistant/scripts/check_config.py create mode 100644 tests/scripts/test_check_config.py diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index b61bce1a58f..4b526c40b38 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -104,7 +104,7 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: try: config = component.CONFIG_SCHEMA(config) except vol.MultipleInvalid as ex: - _log_exception(ex, domain, config) + log_exception(ex, domain, config) return False elif hasattr(component, 'PLATFORM_SCHEMA'): @@ -114,7 +114,7 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: try: p_validated = component.PLATFORM_SCHEMA(p_config) except vol.MultipleInvalid as ex: - _log_exception(ex, domain, p_config) + log_exception(ex, domain, p_config) return False # Not all platform components follow same pattern for platforms @@ -135,8 +135,8 @@ def _setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: try: p_validated = platform.PLATFORM_SCHEMA(p_validated) except vol.MultipleInvalid as ex: - _log_exception(ex, '{}.{}'.format(domain, p_name), - p_validated) + log_exception(ex, '{}.{}'.format(domain, p_name), + p_validated) return False platforms.append(p_validated) @@ -240,7 +240,7 @@ def from_config_dict(config: Dict[str, Any], try: conf_util.process_ha_core_config(hass, core_config) except vol.Invalid as ex: - _log_exception(ex, 'homeassistant', core_config) + log_exception(ex, 'homeassistant', core_config) return None conf_util.process_ha_config_upgrade(hass) @@ -374,7 +374,7 @@ def _ensure_loader_prepared(hass: core.HomeAssistant) -> None: loader.prepare(hass) -def _log_exception(ex, domain, config): +def log_exception(ex, domain, config): """Generate log exception for config validation.""" message = 'Invalid config for [{}]: '.format(domain) if 'extra keys not allowed' in ex.error_message: diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py new file mode 100644 index 00000000000..6105cb47cb2 --- /dev/null +++ b/homeassistant/scripts/check_config.py @@ -0,0 +1,261 @@ +"""Script to ensure a configuration file exists.""" +import argparse +import os +from glob import glob +import logging +from typing import List, Dict, Sequence +from unittest.mock import patch +from platform import system + +from homeassistant.exceptions import HomeAssistantError +import homeassistant.bootstrap as bootstrap +import homeassistant.config as config_util +import homeassistant.loader as loader +import homeassistant.util.yaml as yaml + +REQUIREMENTS = ('colorlog>2.1<3',) +if system() == 'Windows': # Ensure colorama installed for colorlog on Windows + REQUIREMENTS += ('colorama<=1',) + +_LOGGER = logging.getLogger(__name__) +# pylint: disable=protected-access +MOCKS = { + 'load': ("homeassistant.util.yaml.load_yaml", yaml.load_yaml), + 'get': ("homeassistant.loader.get_component", loader.get_component), + 'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml), + 'except': ("homeassistant.bootstrap.log_exception", + bootstrap.log_exception) +} +SILENCE = ( + 'homeassistant.util.yaml.clear_secret_cache', + 'homeassistant.core._LOGGER.info', + 'homeassistant.loader._LOGGER.info', + 'homeassistant.bootstrap._LOGGER.info', + 'homeassistant.bootstrap._LOGGER.warning', + 'homeassistant.util.yaml._LOGGER.debug', +) +PATCHES = {} + +C_HEAD = 'bold' +ERROR_STR = 'General Errors' + + +def color(the_color, *args, reset=None): + """Color helper.""" + from colorlog.escape_codes import escape_codes, parse_colors + try: + if len(args) == 0: + assert reset is None, "You cannot reset if nothing being printed" + return parse_colors(the_color) + return parse_colors(the_color) + ' '.join(args) + \ + escape_codes[reset or 'reset'] + except KeyError as k: + raise ValueError("Invalid color {} in {}".format(str(k), the_color)) + + +# pylint: disable=too-many-locals, too-many-branches +def run(script_args: List) -> int: + """Handle ensure config commandline script.""" + parser = argparse.ArgumentParser( + description=("Check Home Assistant configuration.")) + parser.add_argument( + '--script', choices=['check_config']) + parser.add_argument( + '-c', '--config', + default=config_util.get_default_config_dir(), + help="Directory that contains the Home Assistant configuration") + parser.add_argument( + '-i', '--info', + default=None, + help="Show a portion of the config") + parser.add_argument( + '-f', '--files', + action='store_true', + help="Show used configuration files") + parser.add_argument( + '-s', '--secrets', + action='store_true', + help="Show secret information") + + args = parser.parse_args() + + config_dir = os.path.join(os.getcwd(), args.config) + config_path = os.path.join(config_dir, 'configuration.yaml') + if not os.path.isfile(config_path): + print('Config does not exist:', config_path) + return 1 + + print(color('bold', "Testing configuration at", config_dir)) + + domain_info = [] + if args.info: + domain_info = args.info.split(',') + + res = check(config_path) + + if args.files: + print(color(C_HEAD, 'yaml files'), '(used /', + color('red', 'not used')+')') + # Python 3.5 gets a recursive, but not in 3.4 + for yfn in sorted(glob(os.path.join(config_dir, '*.yaml')) + + glob(os.path.join(config_dir, '*/*.yaml'))): + the_color = '' if yfn in res['yaml_files'] else 'red' + print(color(the_color, '-', yfn)) + + if len(res['except']) > 0: + print(color('bold_white', 'Failed config')) + for domain, config in res['except'].items(): + domain_info.append(domain) + print(' ', color('bold_red', domain + ':'), + color('red', '', reset='red')) + dump_dict(config, reset='red', indent_count=3) + print(color('reset')) + + if domain_info: + if 'all' in domain_info: + print(color('bold_white', 'Successful config (all)')) + for domain, config in res['components']: + print(color(C_HEAD, domain + ':')) + dump_dict(config, indent_count=3) + else: + print(color('bold_white', 'Successful config (partial)')) + for domain in domain_info: + if domain == ERROR_STR: + continue + print(' ', color(C_HEAD, domain + ':')) + dump_dict(res['components'].get(domain, None), indent_count=3) + + if args.secrets: + flatsecret = {} + + for sfn, sdict in res['secret_cache'].items(): + sss = [] + for skey, sval in sdict.items(): + if skey in flatsecret: + _LOGGER.error('Duplicated secrets in files %s and %s', + flatsecret[skey], sfn) + flatsecret[skey] = sfn + sss.append(color('green', skey) if skey in res['secrets'] + else skey) + print(color(C_HEAD, 'Secrets from', sfn + ':'), ', '.join(sss)) + + print(color(C_HEAD, 'Used Secrets:')) + for skey, sval in res['secrets'].items(): + print(' -', skey + ':', sval, color('cyan', '[from:', flatsecret + .get(skey, 'keyring') + ']')) + + return 0 + + +def check(config_path): + """Perform a check by mocking hass load functions.""" + res = { + 'yaml_files': {}, # yaml_files loaded + 'secrets': {}, # secret cache and secrets loaded + 'except': {}, # exceptions raised (with config) + 'components': {}, # successful components + 'secret_cache': {}, + } + + def mock_load(filename): # pylint: disable=unused-variable + """Mock hass.util.load_yaml to save config files.""" + res['yaml_files'][filename] = True + return MOCKS['load'][1](filename) + + def mock_get(comp_name): # pylint: disable=unused-variable + """Mock hass.loader.get_component to replace setup & setup_platform.""" + def mock_setup(*kwargs): + """Mock setup, only record the component name & config.""" + assert comp_name not in res['components'], \ + "Components should contain a list of platforms" + res['components'][comp_name] = kwargs[1].get(comp_name) + return True + module = MOCKS['get'][1](comp_name) + + if module is None: + # Ensure list + res['except'][ERROR_STR] = res['except'].get(ERROR_STR, []) + res['except'][ERROR_STR].append('{} not found: {}'.format( + 'Platform' if '.' in comp_name else 'Component', comp_name)) + return None + + # Test if platform/component and overwrite setup + if '.' in comp_name: + module.setup_platform = mock_setup + else: + module.setup = mock_setup + + return module + + def mock_secrets(ldr, node): # pylint: disable=unused-variable + """Mock _get_secrets.""" + try: + val = MOCKS['secrets'][1](ldr, node) + except HomeAssistantError: + val = None + res['secrets'][node.value] = val + return val + + def mock_except(ex, domain, config): # pylint: disable=unused-variable + """Mock bootstrap.log_exception.""" + MOCKS['except'][1](ex, domain, config) + res['except'][domain] = config.get(domain, config) + + # Patches to skip functions + for sil in SILENCE: + PATCHES[sil] = patch(sil) + + # Patches with local mock functions + for key, val in MOCKS.items(): + mock_function = locals()['mock_'+key] + PATCHES[key] = patch(val[0], side_effect=mock_function) + + # Start all patches + for pat in PATCHES.values(): + pat.start() + # Ensure !secrets point to the patched function + yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) + + try: + bootstrap.from_config_file(config_path, skip_pip=True) + print(dir(yaml)) + res['secret_cache'] = yaml.__SECRET_CACHE + return res + finally: + # Stop all patches + for pat in PATCHES.values(): + pat.stop() + # Ensure !secrets point to the original function + yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) + + +def dump_dict(layer, indent_count=1, listi=False, **kwargs): + """Display a dict. + + A friendly version of print yaml.yaml.dump(config). + """ + def line_src(this): + """Display line config source.""" + if hasattr(this, '__config_file__'): + return color('cyan', "[source {}:{}]" + .format(this.__config_file__, this.__line__ or '?'), + **kwargs) + return '' + + indent_str = indent_count * ' ' + if listi or isinstance(layer, list): + indent_str = indent_str[:-1]+'-' + if isinstance(layer, Dict): + for key, value in layer.items(): + if isinstance(value, dict) or isinstance(value, list): + print(indent_str, key + ':', line_src(value)) + dump_dict(value, indent_count+2) + else: + print(indent_str, key + ':', value) + indent_str = indent_count * ' ' + if isinstance(layer, Sequence): + for i in layer: + if isinstance(i, dict): + dump_dict(i, indent_count, True) + else: + print(indent_str, i) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index ddbc53b075c..6696b5434f2 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -46,7 +46,7 @@ def load_yaml(fname: str) -> Union[List, Dict]: def clear_secret_cache() -> None: - """Clear the secrete cache.""" + """Clear the secret cache.""" __SECRET_CACHE.clear() @@ -150,10 +150,8 @@ def _env_var_yaml(loader: SafeLineLoader, def _load_secret_yaml(secret_path: str) -> Dict: """Load the secrets yaml from path.""" _LOGGER.debug('Loading %s', os.path.join(secret_path, _SECRET_YAML)) - secrets = {} - if os.path.isfile(os.path.join(secret_path, _SECRET_YAML)): - secrets = load_yaml( - os.path.join(secret_path, _SECRET_YAML)) + try: + secrets = load_yaml(os.path.join(secret_path, _SECRET_YAML)) if 'logger' in secrets: logger = str(secrets['logger']).lower() if logger == 'debug': @@ -162,7 +160,9 @@ def _load_secret_yaml(secret_path: str) -> Dict: _LOGGER.error("secrets.yaml: 'logger: debug' expected," " but 'logger: %s' found", logger) del secrets['logger'] - return secrets + return secrets + except FileNotFoundError: + return {} # pylint: disable=protected-access @@ -170,24 +170,23 @@ def _secret_yaml(loader: SafeLineLoader, node: yaml.nodes.Node): """Load secrets and embed it into the configuration YAML.""" secret_path = os.path.dirname(loader.name) - while os.path.exists(secret_path): + while True: secrets = __SECRET_CACHE.get(secret_path, _load_secret_yaml(secret_path)) if node.value in secrets: _LOGGER.debug('Secret %s retrieved from secrets.yaml in ' 'folder %s', node.value, secret_path) return secrets[node.value] - next_path = os.path.dirname(secret_path) - if not next_path or next_path == secret_path \ - or secret_path == os.path.dirname(sys.path[0]): - # Somehow we got past the .homeassistant configuration folder... - break + if secret_path == os.path.dirname(sys.path[0]): + break # sys.path[0] set to config/deps folder by bootstrap - secret_path = next_path + secret_path = os.path.dirname(secret_path) + if not os.path.exists(secret_path) or len(secret_path) < 5: + break # Somehow we got past the .homeassistant config folder if keyring: - # do ome keyring stuff + # do some keyring stuff pwd = keyring.get_password(_SECRET_NAMESPACE, node.value) if pwd: _LOGGER.debug('Secret %s retrieved from keyring.', node.value) diff --git a/requirements_all.txt b/requirements_all.txt index 6e108ce3c01..c974f37799d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -52,6 +52,9 @@ boto3==1.3.1 # homeassistant.components.http cherrypy==7.1.0 +# homeassistant.scripts.check_config +colorlog>2.1<3 + # homeassistant.components.media_player.directv directpy==0.1 @@ -205,6 +208,9 @@ insteon_hub==0.4.5 # homeassistant.components.media_player.kodi jsonrpc-requests==0.3 +# homeassistant.scripts.keyring +keyring>=9.3,<10.0 + # homeassistant.components.knx knxip==0.3.3 @@ -432,6 +438,7 @@ somecomfort==0.2.1 speedtest-cli==0.3.4 # homeassistant.components.recorder +# homeassistant.scripts.db_migrator sqlalchemy==1.0.14 # homeassistant.components.http diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 2ca7339e127..8621cb24c95 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -31,7 +31,7 @@ def explore_module(package, explore_children): if not hasattr(module, '__path__'): return found - for _, name, ispkg in pkgutil.iter_modules(module.__path__, package + '.'): + for _, name, _ in pkgutil.iter_modules(module.__path__, package + '.'): found.append(name) if explore_children: @@ -60,7 +60,8 @@ def gather_modules(): errors = [] output = [] - for package in sorted(explore_module('homeassistant.components', True)): + for package in sorted(explore_module('homeassistant.components', True) + + explore_module('homeassistant.scripts', True)): try: module = importlib.import_module(package) except ImportError: diff --git a/tests/common.py b/tests/common.py index b0e3ef17653..5d1f485d7fe 100644 --- a/tests/common.py +++ b/tests/common.py @@ -2,12 +2,16 @@ import os from datetime import timedelta from unittest import mock +from unittest.mock import patch +from io import StringIO +import logging from homeassistant import core as ha, loader from homeassistant.bootstrap import _setup_component from homeassistant.helpers.entity import ToggleEntity from homeassistant.util.unit_system import METRIC_SYSTEM import homeassistant.util.dt as date_util +import homeassistant.util.yaml as yaml from homeassistant.const import ( STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED, EVENT_PLATFORM_DISCOVERED, ATTR_SERVICE, @@ -15,11 +19,12 @@ from homeassistant.const import ( from homeassistant.components import sun, mqtt _TEST_INSTANCE_PORT = SERVER_PORT +_LOGGER = logging.getLogger(__name__) -def get_test_config_dir(): +def get_test_config_dir(*add_path): """Return a path to a test config dir.""" - return os.path.join(os.path.dirname(__file__), "testing_config") + return os.path.join(os.path.dirname(__file__), "testing_config", *add_path) def get_test_home_assistant(num_threads=None): @@ -65,8 +70,7 @@ def mock_service(hass, domain, service): """ calls = [] - hass.services.register( - domain, service, lambda call: calls.append(call)) + hass.services.register(domain, service, calls.append) return calls @@ -110,8 +114,8 @@ def ensure_sun_set(hass): def load_fixture(filename): """Helper to load a fixture.""" path = os.path.join(os.path.dirname(__file__), 'fixtures', filename) - with open(path) as fp: - return fp.read() + with open(path) as fptr: + return fptr.read() def mock_state_change_event(hass, new_state, old_state=None): @@ -147,6 +151,7 @@ def mock_mqtt_component(hass, mock_mqtt): class MockModule(object): """Representation of a fake module.""" + # pylint: disable=invalid-name,too-few-public-methods,too-many-arguments def __init__(self, domain=None, dependencies=None, setup=None, requirements=None, config_schema=None, platform_schema=None): """Initialize the mock module.""" @@ -170,6 +175,7 @@ class MockModule(object): class MockPlatform(object): """Provide a fake platform.""" + # pylint: disable=invalid-name,too-few-public-methods def __init__(self, setup_platform=None, dependencies=None, platform_schema=None): """Initialize the platform.""" @@ -234,3 +240,33 @@ class MockToggleDevice(ToggleEntity): if call[0] == method) except StopIteration: return None + + +def patch_yaml_files(files_dict, endswith=True): + """Patch load_yaml with a dictionary of yaml files.""" + # match using endswith, start search with longest string + matchlist = sorted(list(files_dict.keys()), key=len) if endswith else [] + # matchlist.sort(key=len) + + def mock_open_f(fname, **_): + """Mock open() in the yaml module, used by load_yaml.""" + # Return the mocked file on full match + if fname in files_dict: + _LOGGER.debug('patch_yaml_files match %s', fname) + return StringIO(files_dict[fname]) + + # Match using endswith + for ends in matchlist: + if fname.endswith(ends): + _LOGGER.debug('patch_yaml_files end match %s: %s', ends, fname) + return StringIO(files_dict[ends]) + + # Fallback for hass.components (i.e. services.yaml) + if 'homeassistant/components' in fname: + _LOGGER.debug('patch_yaml_files using real file: %s', fname) + return open(fname, encoding='utf-8') + + # Not found + raise IOError('File not found: {}'.format(fname)) + + return patch.object(yaml, 'open', mock_open_f, create=True) diff --git a/tests/scripts/test_check_config.py b/tests/scripts/test_check_config.py new file mode 100644 index 00000000000..4cad9504f0c --- /dev/null +++ b/tests/scripts/test_check_config.py @@ -0,0 +1,126 @@ +"""Test check_config script.""" +import unittest +import logging +import os + +import homeassistant.scripts.check_config as check_config +from tests.common import patch_yaml_files, get_test_config_dir + +_LOGGER = logging.getLogger(__name__) + +BASE_CONFIG = ( + 'homeassistant:\n' + ' name: Home\n' + ' latitude: -26.107361\n' + ' longitude: 28.054500\n' + ' elevation: 1600\n' + ' unit_system: metric\n' + ' time_zone: GMT\n' + '\n\n' +) + + +def tearDownModule(self): # pylint: disable=invalid-name + """Clean files.""" + # .HA_VERSION created during bootstrap's config update + path = get_test_config_dir('.HA_VERSION') + if os.path.isfile(path): + os.remove(path) + + +class TestCheckConfig(unittest.TestCase): + """Tests for the homeassistant.scripts.check_config module.""" + + # pylint: disable=no-self-use,invalid-name + def test_config_platform_valid(self): + """Test a valid platform setup.""" + files = { + 'light.yaml': BASE_CONFIG + 'light:\n platform: hue', + } + with patch_yaml_files(files): + res = check_config.check(get_test_config_dir('light.yaml')) + self.assertDictEqual({ + 'components': {'light': [{'platform': 'hue'}]}, + 'except': {}, + 'secret_cache': {}, + 'secrets': {}, + 'yaml_files': {} + }, res) + + def test_config_component_platform_fail_validation(self): + """Test errors if component & platform not found.""" + files = { + 'component.yaml': BASE_CONFIG + 'http:\n password: err123', + } + with patch_yaml_files(files): + res = check_config.check(get_test_config_dir('component.yaml')) + self.assertDictEqual({ + 'components': {}, + 'except': {'http': {'password': 'err123'}}, + 'secret_cache': {}, + 'secrets': {}, + 'yaml_files': {} + }, res) + + files = { + 'platform.yaml': (BASE_CONFIG + 'mqtt:\n\n' + 'light:\n platform: mqtt_json'), + } + with patch_yaml_files(files): + res = check_config.check(get_test_config_dir('platform.yaml')) + self.assertDictEqual({ + 'components': {'mqtt': {'keepalive': 60, 'port': 1883, + 'protocol': '3.1.1'}}, + 'except': {'light.mqtt_json': {'platform': 'mqtt_json'}}, + 'secret_cache': {}, + 'secrets': {}, + 'yaml_files': {} + }, res) + + def test_component_platform_not_found(self): + """Test errors if component or platform not found.""" + files = { + 'badcomponent.yaml': BASE_CONFIG + 'beer:', + 'badplatform.yaml': BASE_CONFIG + 'light:\n platform: beer', + } + with patch_yaml_files(files): + res = check_config.check(get_test_config_dir('badcomponent.yaml')) + self.assertDictEqual({ + 'components': {}, + 'except': {check_config.ERROR_STR: + ['Component not found: beer']}, + 'secret_cache': {}, + 'secrets': {}, + 'yaml_files': {} + }, res) + + res = check_config.check(get_test_config_dir('badplatform.yaml')) + self.assertDictEqual({ + 'components': {}, + 'except': {check_config.ERROR_STR: + ['Platform not found: light.beer']}, + 'secret_cache': {}, + 'secrets': {}, + 'yaml_files': {} + }, res) + + def test_secrets(self): + """Test secrets config checking method.""" + files = { + 'secret.yaml': (BASE_CONFIG + + 'http:\n' + ' api_password: !secret http_pw'), + 'secrets.yaml': ('logger: debug\n' + 'http_pw: abc123'), + } + + with patch_yaml_files(files): + res = check_config.check(get_test_config_dir('secret.yaml')) + self.assertDictEqual({ + 'components': {'http': {'api_password': 'abc123', + 'server_port': 8123}}, + 'except': {}, + 'secret_cache': {}, + 'secrets': {'http_pw': 'abc123'}, + 'yaml_files': {'secrets.yaml': True} + }, res) From c9d5d1a417dad60a41199f5940a7540474b6201c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 22 Aug 2016 21:44:58 -0700 Subject: [PATCH 140/193] Remove debug print --- homeassistant/scripts/check_config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index 6105cb47cb2..47c1e3b3f64 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -218,7 +218,6 @@ def check(config_path): try: bootstrap.from_config_file(config_path, skip_pip=True) - print(dir(yaml)) res['secret_cache'] = yaml.__SECRET_CACHE return res finally: From 82de1cd6fe202280f08ad1cf40d6bf9972380244 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Mon, 22 Aug 2016 23:15:22 -0700 Subject: [PATCH 141/193] change const.py to use single quotes --- homeassistant/const.py | 198 ++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 4bf1785fe7b..e2e76d8b86e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """Constants used by Home Assistant components.""" -__version__ = "0.27.0.dev0" +__version__ = '0.27.0.dev0' REQUIRED_PYTHON_VER = (3, 4) PLATFORM_FORMAT = '{}.{}' @@ -10,7 +10,7 @@ PLATFORM_FORMAT = '{}.{}' MATCH_ALL = '*' # If no name is specified -DEVICE_DEFAULT_NAME = "Unnamed Device" +DEVICE_DEFAULT_NAME = 'Unnamed Device' WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] @@ -74,15 +74,15 @@ CONF_WHITELIST = 'whitelist' CONF_ZONE = 'zone' # #### EVENTS #### -EVENT_HOMEASSISTANT_START = "homeassistant_start" -EVENT_HOMEASSISTANT_STOP = "homeassistant_stop" -EVENT_STATE_CHANGED = "state_changed" -EVENT_TIME_CHANGED = "time_changed" -EVENT_CALL_SERVICE = "call_service" -EVENT_SERVICE_EXECUTED = "service_executed" -EVENT_PLATFORM_DISCOVERED = "platform_discovered" -EVENT_COMPONENT_LOADED = "component_loaded" -EVENT_SERVICE_REGISTERED = "service_registered" +EVENT_HOMEASSISTANT_START = 'homeassistant_start' +EVENT_HOMEASSISTANT_STOP = 'homeassistant_stop' +EVENT_STATE_CHANGED = 'state_changed' +EVENT_TIME_CHANGED = 'time_changed' +EVENT_CALL_SERVICE = 'call_service' +EVENT_SERVICE_EXECUTED = 'service_executed' +EVENT_PLATFORM_DISCOVERED = 'platform_discovered' +EVENT_COMPONENT_LOADED = 'component_loaded' +EVENT_SERVICE_REGISTERED = 'service_registered' # #### STATES #### STATE_ON = 'on' @@ -107,94 +107,94 @@ STATE_UNAVAILABLE = 'unavailable' # #### STATE AND EVENT ATTRIBUTES #### # Contains current time for a TIME_CHANGED event -ATTR_NOW = "now" +ATTR_NOW = 'now' # Contains domain, service for a SERVICE_CALL event -ATTR_DOMAIN = "domain" -ATTR_SERVICE = "service" -ATTR_SERVICE_DATA = "service_data" +ATTR_DOMAIN = 'domain' +ATTR_SERVICE = 'service' +ATTR_SERVICE_DATA = 'service_data' # Data for a SERVICE_EXECUTED event -ATTR_SERVICE_CALL_ID = "service_call_id" +ATTR_SERVICE_CALL_ID = 'service_call_id' # Contains one string or a list of strings, each being an entity id ATTR_ENTITY_ID = 'entity_id' # String with a friendly name for the entity -ATTR_FRIENDLY_NAME = "friendly_name" +ATTR_FRIENDLY_NAME = 'friendly_name' # A picture to represent entity -ATTR_ENTITY_PICTURE = "entity_picture" +ATTR_ENTITY_PICTURE = 'entity_picture' # Icon to use in the frontend -ATTR_ICON = "icon" +ATTR_ICON = 'icon' # The unit of measurement if applicable -ATTR_UNIT_OF_MEASUREMENT = "unit_of_measurement" +ATTR_UNIT_OF_MEASUREMENT = 'unit_of_measurement' CONF_UNIT_SYSTEM_METRIC = 'metric' # type: str CONF_UNIT_SYSTEM_IMPERIAL = 'imperial' # type: str # Temperature attribute -ATTR_TEMPERATURE = "temperature" -TEMP_CELSIUS = "°C" -TEMP_FAHRENHEIT = "°F" +ATTR_TEMPERATURE = 'temperature' +TEMP_CELSIUS = '°C' +TEMP_FAHRENHEIT = '°F' # Length units -LENGTH_CENTIMETERS = "cm" # type: str -LENGTH_METERS = "m" # type: str -LENGTH_KILOMETERS = "km" # type: str +LENGTH_CENTIMETERS = 'cm' # type: str +LENGTH_METERS = 'm' # type: str +LENGTH_KILOMETERS = 'km' # type: str -LENGTH_INCHES = "in" # type: str -LENGTH_FEET = "ft" # type: str -LENGTH_YARD = "yd" # type: str -LENGTH_MILES = "mi" # type: str +LENGTH_INCHES = 'in' # type: str +LENGTH_FEET = 'ft' # type: str +LENGTH_YARD = 'yd' # type: str +LENGTH_MILES = 'mi' # type: str # Volume units -VOLUME_LITERS = "L" # type: str -VOLUME_MILLILITERS = "mL" # type: str +VOLUME_LITERS = 'L' # type: str +VOLUME_MILLILITERS = 'mL' # type: str -VOLUME_GALLONS = "gal" # type: str -VOLUME_FLUID_OUNCE = "fl. oz." # type: str +VOLUME_GALLONS = 'gal' # type: str +VOLUME_FLUID_OUNCE = 'fl. oz.' # type: str # Mass units -MASS_GRAMS = "g" # type: str -MASS_KILOGRAMS = "kg" # type: str +MASS_GRAMS = 'g' # type: str +MASS_KILOGRAMS = 'kg' # type: str -MASS_OUNCES = "oz" # type: str -MASS_POUNDS = "lb" # type: str +MASS_OUNCES = 'oz' # type: str +MASS_POUNDS = 'lb' # type: str # Contains the information that is discovered -ATTR_DISCOVERED = "discovered" +ATTR_DISCOVERED = 'discovered' # Location of the device/sensor -ATTR_LOCATION = "location" +ATTR_LOCATION = 'location' -ATTR_BATTERY_LEVEL = "battery_level" +ATTR_BATTERY_LEVEL = 'battery_level' # For devices which support a code attribute ATTR_CODE = 'code' ATTR_CODE_FORMAT = 'code_format' # For devices which support an armed state -ATTR_ARMED = "device_armed" +ATTR_ARMED = 'device_armed' # For devices which support a locked state -ATTR_LOCKED = "locked" +ATTR_LOCKED = 'locked' # For sensors that support 'tripping', eg. motion and door sensors -ATTR_TRIPPED = "device_tripped" +ATTR_TRIPPED = 'device_tripped' # For sensors that support 'tripping' this holds the most recent # time the device was tripped -ATTR_LAST_TRIP_TIME = "last_tripped_time" +ATTR_LAST_TRIP_TIME = 'last_tripped_time' # For all entity's, this hold whether or not it should be hidden -ATTR_HIDDEN = "hidden" +ATTR_HIDDEN = 'hidden' # Location of the entity -ATTR_LATITUDE = "latitude" -ATTR_LONGITUDE = "longitude" +ATTR_LATITUDE = 'latitude' +ATTR_LONGITUDE = 'longitude' # Accuracy of location in meters ATTR_GPS_ACCURACY = 'gps_accuracy' @@ -203,35 +203,35 @@ ATTR_GPS_ACCURACY = 'gps_accuracy' ATTR_ASSUMED_STATE = 'assumed_state' # #### SERVICES #### -SERVICE_HOMEASSISTANT_STOP = "stop" -SERVICE_HOMEASSISTANT_RESTART = "restart" +SERVICE_HOMEASSISTANT_STOP = 'stop' +SERVICE_HOMEASSISTANT_RESTART = 'restart' SERVICE_TURN_ON = 'turn_on' SERVICE_TURN_OFF = 'turn_off' SERVICE_TOGGLE = 'toggle' -SERVICE_VOLUME_UP = "volume_up" -SERVICE_VOLUME_DOWN = "volume_down" -SERVICE_VOLUME_MUTE = "volume_mute" -SERVICE_VOLUME_SET = "volume_set" -SERVICE_MEDIA_PLAY_PAUSE = "media_play_pause" -SERVICE_MEDIA_PLAY = "media_play" -SERVICE_MEDIA_PAUSE = "media_pause" -SERVICE_MEDIA_STOP = "media_stop" -SERVICE_MEDIA_NEXT_TRACK = "media_next_track" -SERVICE_MEDIA_PREVIOUS_TRACK = "media_previous_track" -SERVICE_MEDIA_SEEK = "media_seek" +SERVICE_VOLUME_UP = 'volume_up' +SERVICE_VOLUME_DOWN = 'volume_down' +SERVICE_VOLUME_MUTE = 'volume_mute' +SERVICE_VOLUME_SET = 'volume_set' +SERVICE_MEDIA_PLAY_PAUSE = 'media_play_pause' +SERVICE_MEDIA_PLAY = 'media_play' +SERVICE_MEDIA_PAUSE = 'media_pause' +SERVICE_MEDIA_STOP = 'media_stop' +SERVICE_MEDIA_NEXT_TRACK = 'media_next_track' +SERVICE_MEDIA_PREVIOUS_TRACK = 'media_previous_track' +SERVICE_MEDIA_SEEK = 'media_seek' -SERVICE_ALARM_DISARM = "alarm_disarm" -SERVICE_ALARM_ARM_HOME = "alarm_arm_home" -SERVICE_ALARM_ARM_AWAY = "alarm_arm_away" -SERVICE_ALARM_TRIGGER = "alarm_trigger" +SERVICE_ALARM_DISARM = 'alarm_disarm' +SERVICE_ALARM_ARM_HOME = 'alarm_arm_home' +SERVICE_ALARM_ARM_AWAY = 'alarm_arm_away' +SERVICE_ALARM_TRIGGER = 'alarm_trigger' -SERVICE_LOCK = "lock" -SERVICE_UNLOCK = "unlock" +SERVICE_LOCK = 'lock' +SERVICE_UNLOCK = 'unlock' -SERVICE_OPEN = "open" -SERVICE_CLOSE = "close" +SERVICE_OPEN = 'open' +SERVICE_CLOSE = 'close' SERVICE_MOVE_UP = 'move_up' SERVICE_MOVE_DOWN = 'move_down' @@ -241,22 +241,22 @@ SERVICE_STOP = 'stop' # #### API / REMOTE #### SERVER_PORT = 8123 -URL_ROOT = "/" -URL_API = "/api/" -URL_API_STREAM = "/api/stream" -URL_API_CONFIG = "/api/config" -URL_API_DISCOVERY_INFO = "/api/discovery_info" -URL_API_STATES = "/api/states" -URL_API_STATES_ENTITY = "/api/states/{}" -URL_API_EVENTS = "/api/events" -URL_API_EVENTS_EVENT = "/api/events/{}" -URL_API_SERVICES = "/api/services" -URL_API_SERVICES_SERVICE = "/api/services/{}/{}" -URL_API_EVENT_FORWARD = "/api/event_forwarding" -URL_API_COMPONENTS = "/api/components" -URL_API_ERROR_LOG = "/api/error_log" -URL_API_LOG_OUT = "/api/log_out" -URL_API_TEMPLATE = "/api/template" +URL_ROOT = '/' +URL_API = '/api/' +URL_API_STREAM = '/api/stream' +URL_API_CONFIG = '/api/config' +URL_API_DISCOVERY_INFO = '/api/discovery_info' +URL_API_STATES = '/api/states' +URL_API_STATES_ENTITY = '/api/states/{}' +URL_API_EVENTS = '/api/events' +URL_API_EVENTS_EVENT = '/api/events/{}' +URL_API_SERVICES = '/api/services' +URL_API_SERVICES_SERVICE = '/api/services/{}/{}' +URL_API_EVENT_FORWARD = '/api/event_forwarding' +URL_API_COMPONENTS = '/api/components' +URL_API_ERROR_LOG = '/api/error_log' +URL_API_LOG_OUT = '/api/log_out' +URL_API_TEMPLATE = '/api/template' HTTP_OK = 200 HTTP_CREATED = 201 @@ -268,25 +268,25 @@ HTTP_METHOD_NOT_ALLOWED = 405 HTTP_UNPROCESSABLE_ENTITY = 422 HTTP_INTERNAL_SERVER_ERROR = 500 -HTTP_HEADER_HA_AUTH = "X-HA-access" -HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding" -HTTP_HEADER_CONTENT_TYPE = "Content-type" -HTTP_HEADER_CONTENT_ENCODING = "Content-Encoding" -HTTP_HEADER_VARY = "Vary" -HTTP_HEADER_CONTENT_LENGTH = "Content-Length" -HTTP_HEADER_CACHE_CONTROL = "Cache-Control" -HTTP_HEADER_EXPIRES = "Expires" -HTTP_HEADER_ORIGIN = "Origin" -HTTP_HEADER_X_REQUESTED_WITH = "X-Requested-With" -HTTP_HEADER_ACCEPT = "Accept" -HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin" -HTTP_HEADER_ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers" +HTTP_HEADER_HA_AUTH = 'X-HA-access' +HTTP_HEADER_ACCEPT_ENCODING = 'Accept-Encoding' +HTTP_HEADER_CONTENT_TYPE = 'Content-type' +HTTP_HEADER_CONTENT_ENCODING = 'Content-Encoding' +HTTP_HEADER_VARY = 'Vary' +HTTP_HEADER_CONTENT_LENGTH = 'Content-Length' +HTTP_HEADER_CACHE_CONTROL = 'Cache-Control' +HTTP_HEADER_EXPIRES = 'Expires' +HTTP_HEADER_ORIGIN = 'Origin' +HTTP_HEADER_X_REQUESTED_WITH = 'X-Requested-With' +HTTP_HEADER_ACCEPT = 'Accept' +HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = 'Access-Control-Allow-Origin' +HTTP_HEADER_ACCESS_CONTROL_ALLOW_HEADERS = 'Access-Control-Allow-Headers' ALLOWED_CORS_HEADERS = [HTTP_HEADER_ORIGIN, HTTP_HEADER_ACCEPT, HTTP_HEADER_X_REQUESTED_WITH, HTTP_HEADER_CONTENT_TYPE, HTTP_HEADER_HA_AUTH] -CONTENT_TYPE_JSON = "application/json" +CONTENT_TYPE_JSON = 'application/json' CONTENT_TYPE_MULTIPART = 'multipart/x-mixed-replace; boundary={}' CONTENT_TYPE_TEXT_PLAIN = 'text/plain' From 5abb46a80956d7772a291602108e200111461142 Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Tue, 23 Aug 2016 07:56:39 +0100 Subject: [PATCH 142/193] Tidy voluptuous. (#2946) --- homeassistant/components/sensor/template.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 0462d664e26..75cbfa97c7d 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -24,7 +24,7 @@ SENSOR_SCHEMA = vol.Schema({ vol.Required(CONF_VALUE_TEMPLATE): cv.template, vol.Optional(ATTR_FRIENDLY_NAME): cv.string, vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string, - vol.Optional(ATTR_ENTITY_ID): cv.entity_ids + vol.Optional(ATTR_ENTITY_ID, default=MATCH_ALL): cv.entity_ids }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -38,11 +38,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors = [] for device, device_config in config[CONF_SENSORS].items(): + state_template = device_config[CONF_VALUE_TEMPLATE] + entity_ids = device_config[ATTR_ENTITY_ID, MATCH_ALL] friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT) - state_template = device_config.get(CONF_VALUE_TEMPLATE) - - entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL) sensors.append( SensorTemplate( From dfd76fc0e608aaa63ca9fe4b0b8f5e96d93da990 Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Tue, 23 Aug 2016 07:57:07 +0100 Subject: [PATCH 143/193] Minor tidy of voluptuous. (#2945) --- homeassistant/components/switch/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/template.py b/homeassistant/components/switch/template.py index 274ff992088..6778315843e 100644 --- a/homeassistant/components/switch/template.py +++ b/homeassistant/components/switch/template.py @@ -32,7 +32,7 @@ SWITCH_SCHEMA = vol.Schema({ vol.Required(ON_ACTION): cv.SCRIPT_SCHEMA, vol.Required(OFF_ACTION): cv.SCRIPT_SCHEMA, vol.Optional(ATTR_FRIENDLY_NAME): cv.string, - vol.Optional(ATTR_ENTITY_ID): cv.entity_ids + vol.Optional(ATTR_ENTITY_ID, default=MATCH_ALL): cv.entity_ids }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -50,7 +50,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): state_template = device_config[CONF_VALUE_TEMPLATE] on_action = device_config[ON_ACTION] off_action = device_config[OFF_ACTION] - entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL) + entity_ids = device_config[ATTR_ENTITY_ID] switches.append( SwitchTemplate( From 88573667fae2f3cf8019c68beb67779d3da4e552 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 23 Aug 2016 00:06:58 -0700 Subject: [PATCH 144/193] Update frontend --- homeassistant/components/frontend/version.py | 2 +- .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 123252 -> 123277 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2279 -> 2278 bytes 6 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 8a5ffe63a79..841c2c495f2 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -2,7 +2,7 @@ FINGERPRINTS = { "core.js": "7901b14f238956024a19139d6c479d68", - "frontend.html": "b33df7a012ea6d2aaf353c4466d6554a", + "frontend.html": "850075be728fcdb83328cf2cb50a9f03", "mdi.html": "710b84acc99b32514f52291aba9cd8e8", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index e99fe69c8e7..ff7a7bc71bd 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ },_distributeDirtyRoots:function(){for(var e,t=this.shadyRoot._dirtyRoots,o=0,i=t.length;o0?~setTimeout(e,t):(this._twiddle.textContent=this._twiddleContent++,this._callbacks.push(e),this._currVal++)},cancel:function(e){if(e<0)clearTimeout(~e);else{var t=e-this._lastVal;if(t>=0){if(!this._callbacks[t])throw"invalid async handle: "+e;this._callbacks[t]=null}}},_atEndOfMicrotask:function(){for(var e=this._callbacks.length,t=0;t \ No newline at end of file +this.currentTarget=t,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()},i=window.Element.prototype.animate;window.Element.prototype.animate=function(n,r){var o=i.call(this,n,r);o._cancelHandlers=[],o.oncancel=null;var a=o.cancel;o.cancel=function(){a.call(this);var i=new e(this,null,t()),n=this._cancelHandlers.concat(this.oncancel?[this.oncancel]:[]);setTimeout(function(){n.forEach(function(t){t.call(i.target,i)})},0)};var s=o.addEventListener;o.addEventListener=function(t,e){"function"==typeof e&&"cancel"==t?this._cancelHandlers.push(e):s.call(this,t,e)};var u=o.removeEventListener;return o.removeEventListener=function(t,e){if("cancel"==t){var i=this._cancelHandlers.indexOf(e);i>=0&&this._cancelHandlers.splice(i,1)}else u.call(this,t,e)},o}}}(),function(t){var e=document.documentElement,i=null,n=!1;try{var r=getComputedStyle(e).getPropertyValue("opacity"),o="0"==r?"1":"0";i=e.animate({opacity:[o,o]},{duration:1}),i.currentTime=0,n=getComputedStyle(e).getPropertyValue("opacity")==o}catch(t){}finally{i&&i.cancel()}if(!n){var a=window.Element.prototype.animate;window.Element.prototype.animate=function(e,i){return window.Symbol&&Symbol.iterator&&Array.prototype.from&&e[Symbol.iterator]&&(e=Array.from(e)),Array.isArray(e)||null===e||(e=t.convertToArrayForm(e)),a.call(this,e,i)}}}(c),!function(t,e,i){function n(t){var i=e.timeline;i.currentTime=t,i._discardAnimations(),0==i._animations.length?o=!1:requestAnimationFrame(n)}var r=window.requestAnimationFrame;window.requestAnimationFrame=function(t){return r(function(i){e.timeline._updateAnimationsPromises(),t(i),e.timeline._updateAnimationsPromises()})},e.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},e.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},_updateAnimationsPromises:function(){e.animationsWithPromises=e.animationsWithPromises.filter(function(t){return t._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(t){return"finished"!=t.playState&&"idle"!=t.playState})},_play:function(t){var i=new e.Animation(t,this);return this._animations.push(i),e.restartWebAnimationsNextTick(),i._updatePromises(),i._animation.play(),i._updatePromises(),i},play:function(t){return t&&t.remove(),this._play(t)}};var o=!1;e.restartWebAnimationsNextTick=function(){o||(o=!0,requestAnimationFrame(n))};var a=new e.AnimationTimeline;e.timeline=a;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return a}})}catch(t){}try{window.document.timeline=a}catch(t){}}(c,e,f),function(t,e,i){e.animationsWithPromises=[],e.Animation=function(e,i){if(this.id="",e&&e._id&&(this.id=e._id),this.effect=e,e&&(e._animation=this),!i)throw new Error("Animation with null timeline is not supported");this._timeline=i,this._sequenceNumber=t.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},e.Animation.prototype={_updatePromises:function(){var t=this._oldPlayState,e=this.playState;return this._readyPromise&&e!==t&&("idle"==e?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==t?this._resolveReadyPromise():"pending"==e&&(this._readyPromise=void 0)),this._finishedPromise&&e!==t&&("idle"==e?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==e?this._resolveFinishedPromise():"finished"==t&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var t,i,n,r,o=!!this._animation;o&&(t=this.playbackRate,i=this._paused,n=this.startTime,r=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=e.newUnderlyingAnimationForKeyframeEffect(this.effect),e.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=e.newUnderlyingAnimationForGroup(this.effect),e.bindAnimationForGroup(this)),this.effect&&this.effect._onsample&&e.bindAnimationForCustomEffect(this),o&&(1!=t&&(this.playbackRate=t),null!==n?this.startTime=n:null!==r?this.currentTime=r:null!==this._holdTime&&(this.currentTime=this._holdTime),i&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var t=this.effect._timing.delay;this._childAnimations.forEach(function(i){this._arrangeChildren(i,t),this.effect instanceof window.SequenceEffect&&(t+=e.groupChildDuration(i.effect))}.bind(this))}},_setExternalAnimation:function(t){if(this.effect&&this._isGroup)for(var e=0;e \ 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 20a48a1f014d0d43a1eb7c60b844615ac0be5471..ed3a49ed807e769a955c602e0004d5fdbc3b421c 100644 GIT binary patch delta 14456 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 K(%u>Zum=EQN-gXF delta 14478 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 gd)QU``#?&vWLeJcbS8-yka)-Uj_(1^s)a#o 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 z zds~BZg+*LnIgj09byJI9O)yumBFKdQZ8J(u_{oWfeW*f4=E%raA(kqtbaX9OEp~=M zwdsyk(5<=N1b1xAu$Az&Q@#1@@QwTD!h!hhhvUgW;MZLo?!3wW0I)+#x-%3203CvP A1ONa4 literal 2279 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 BaykG2 From 2b4f0cb5a163c419755e14647e3dd61132984033 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 23 Aug 2016 00:14:45 -0700 Subject: [PATCH 145/193] Fix broken template sensor tests --- homeassistant/components/sensor/template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 75cbfa97c7d..961b6f39c17 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for device, device_config in config[CONF_SENSORS].items(): state_template = device_config[CONF_VALUE_TEMPLATE] - entity_ids = device_config[ATTR_ENTITY_ID, MATCH_ALL] + entity_ids = device_config[ATTR_ENTITY_ID] friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT) From a43ea81d8e31130853480b3656143746b65c6a03 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 24 Aug 2016 02:27:54 +0200 Subject: [PATCH 146/193] Migrate to voluptuous (#2927) --- homeassistant/components/logentries.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/logentries.py b/homeassistant/components/logentries.py index 5aaaf2df562..ef79b033922 100644 --- a/homeassistant/components/logentries.py +++ b/homeassistant/components/logentries.py @@ -7,29 +7,31 @@ https://home-assistant.io/components/logentries/ import json import logging import requests -import homeassistant.util as util -from homeassistant.const import EVENT_STATE_CHANGED + +import voluptuous as vol + +from homeassistant.const import (CONF_TOKEN, EVENT_STATE_CHANGED) from homeassistant.helpers import state as state_helper -from homeassistant.helpers import validate_config +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -DOMAIN = "logentries" -DEPENDENCIES = [] +DOMAIN = 'logentries' DEFAULT_HOST = 'https://webhook.logentries.com/noformat/logs/' -CONF_TOKEN = 'token' +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_TOKEN): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) def setup(hass, config): """Setup the Logentries component.""" - if not validate_config(config, {DOMAIN: ['token']}, _LOGGER): - _LOGGER.error("Logentries token not present") - return False conf = config[DOMAIN] - token = util.convert(conf.get(CONF_TOKEN), str) - le_wh = DEFAULT_HOST + token + token = conf.get(CONF_TOKEN) + le_wh = '{}{}'.format(DEFAULT_HOST, token) def logentries_event_listener(event): """Listen for new messages on the bus and sends them to Logentries.""" From cf832499cddcc831fa06164ea86f5cd402cb0549 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Wed, 24 Aug 2016 03:23:18 +0200 Subject: [PATCH 147/193] Combine garage_door and rollershutter to cover (#2891) * First draft for cover component * Efficiency from @martinhjelmare * migrate demo * migrate demo test * migrate command_line rollershutter * migrate command_line test * migrate rpi_gpio garage_door * make some abstract methods optional * migrate homematic * migrate scsgate * migrate rfxtrx and test * migrate zwave * migrate wink * migrate mqtt rollershutter and test * requirements * coverage * Update mqtt with garage door * Naming and cleanup * update test_demo.py * update demo and core * Add deprecated warning to rollershutter and garage_door * Naming again * Update * String constants * Make sure set_position works properly in demo too * Make sure position is not set if not available. * Naming, and is_closed * Update zwave.py * requirements * Update test_rfxtrx.py * fix mqtt * requirements * fix wink version * Fixed demo test * naming --- .coveragerc | 4 + homeassistant/components/cover/__init__.py | 234 ++++++++++++++++++ .../components/cover/command_line.py | 128 ++++++++++ homeassistant/components/cover/demo.py | 155 ++++++++++++ homeassistant/components/cover/homematic.py | 101 ++++++++ homeassistant/components/cover/mqtt.py | 167 +++++++++++++ homeassistant/components/cover/rfxtrx.py | 67 +++++ homeassistant/components/cover/rpi_gpio.py | 98 ++++++++ homeassistant/components/cover/scsgate.py | 96 +++++++ homeassistant/components/cover/services.yaml | 71 ++++++ homeassistant/components/cover/wink.py | 64 +++++ homeassistant/components/cover/zwave.py | 184 ++++++++++++++ .../components/garage_door/__init__.py | 3 + .../components/rollershutter/__init__.py | 3 + homeassistant/components/zwave.py | 19 +- homeassistant/const.py | 9 + requirements_all.txt | 2 + tests/components/cover/test_command_line.py | 84 +++++++ tests/components/cover/test_demo.py | 138 +++++++++++ tests/components/cover/test_mqtt.py | 174 +++++++++++++ tests/components/cover/test_rfxtrx.py | 216 ++++++++++++++++ 21 files changed, 2006 insertions(+), 11 deletions(-) create mode 100644 homeassistant/components/cover/__init__.py create mode 100644 homeassistant/components/cover/command_line.py create mode 100644 homeassistant/components/cover/demo.py create mode 100644 homeassistant/components/cover/homematic.py create mode 100644 homeassistant/components/cover/mqtt.py create mode 100644 homeassistant/components/cover/rfxtrx.py create mode 100644 homeassistant/components/cover/rpi_gpio.py create mode 100644 homeassistant/components/cover/scsgate.py create mode 100644 homeassistant/components/cover/services.yaml create mode 100644 homeassistant/components/cover/wink.py create mode 100644 homeassistant/components/cover/zwave.py create mode 100644 tests/components/cover/test_command_line.py create mode 100644 tests/components/cover/test_demo.py create mode 100644 tests/components/cover/test_mqtt.py create mode 100644 tests/components/cover/test_rfxtrx.py diff --git a/.coveragerc b/.coveragerc index b0b7e63f043..8781cf8d4f2 100644 --- a/.coveragerc +++ b/.coveragerc @@ -114,6 +114,10 @@ omit = homeassistant/components/climate/knx.py homeassistant/components/climate/proliphix.py homeassistant/components/climate/radiotherm.py + homeassistant/components/cover/homematic.py + homeassistant/components/cover/rpi_gpio.py + homeassistant/components/cover/scsgate.py + homeassistant/components/cover/wink.py homeassistant/components/device_tracker/actiontec.py homeassistant/components/device_tracker/aruba.py homeassistant/components/device_tracker/asuswrt.py diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py new file mode 100644 index 00000000000..0c74ea4eb31 --- /dev/null +++ b/homeassistant/components/cover/__init__.py @@ -0,0 +1,234 @@ +""" +Support for Cover devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover/ +""" +import os +import logging + +import voluptuous as vol + +from homeassistant.config import load_yaml_config_file +from homeassistant.helpers.entity_component import EntityComponent +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa +import homeassistant.helpers.config_validation as cv +from homeassistant.components import group +from homeassistant.const import ( + SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION, + SERVICE_STOP_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_CLOSE_COVER_TILT, + SERVICE_STOP_COVER_TILT, SERVICE_SET_COVER_TILT_POSITION, STATE_OPEN, + STATE_CLOSED, STATE_UNKNOWN, ATTR_ENTITY_ID) + + +DOMAIN = 'cover' +SCAN_INTERVAL = 15 + +GROUP_NAME_ALL_COVERS = 'all_covers' +ENTITY_ID_ALL_COVERS = group.ENTITY_ID_FORMAT.format( + GROUP_NAME_ALL_COVERS) + +ENTITY_ID_FORMAT = DOMAIN + '.{}' + +_LOGGER = logging.getLogger(__name__) + +ATTR_CURRENT_POSITION = 'current_position' +ATTR_CURRENT_TILT_POSITION = 'current_tilt_position' +ATTR_POSITION = 'position' +ATTR_TILT_POSITION = 'tilt_position' + +COVER_SERVICE_SCHEMA = vol.Schema({ + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, +}) + +COVER_SET_COVER_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({ + vol.Required(ATTR_POSITION): + vol.All(vol.Coerce(int), vol.Range(min=0, max=100)), +}) + +COVER_SET_COVER_TILT_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({ + vol.Required(ATTR_TILT_POSITION): + vol.All(vol.Coerce(int), vol.Range(min=0, max=100)), +}) + +SERVICE_TO_METHOD = { + SERVICE_OPEN_COVER: {'method': 'open_cover'}, + SERVICE_CLOSE_COVER: {'method': 'close_cover'}, + SERVICE_SET_COVER_POSITION: { + 'method': 'set_cover_position', + 'schema': COVER_SET_COVER_POSITION_SCHEMA}, + SERVICE_STOP_COVER: {'method': 'stop_cover'}, + SERVICE_OPEN_COVER_TILT: {'method': 'open_cover_tilt'}, + SERVICE_CLOSE_COVER_TILT: {'method': 'close_cover_tilt'}, + SERVICE_SET_COVER_TILT_POSITION: { + 'method': 'set_cover_tilt_position', + 'schema': COVER_SET_COVER_TILT_POSITION_SCHEMA}, +} + + +def is_closed(hass, entity_id=None): + """Return if the cover is closed based on the statemachine.""" + entity_id = entity_id or ENTITY_ID_ALL_COVERS + return hass.states.is_state(entity_id, STATE_CLOSED) + + +def open_cover(hass, entity_id=None): + """Open all or specified cover.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_OPEN_COVER, data) + + +def close_cover(hass, entity_id=None): + """Close all or specified cover.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_CLOSE_COVER, data) + + +def set_cover_position(hass, position, entity_id=None): + """Move to specific position all or specified cover.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} + data[ATTR_POSITION] = position + hass.services.call(DOMAIN, SERVICE_SET_COVER_POSITION, data) + + +def stop_cover(hass, entity_id=None): + """Stop all or specified cover.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_STOP_COVER, data) + + +def open_cover_tilt(hass, entity_id=None): + """Open all or specified cover tilt.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_OPEN_COVER_TILT, data) + + +def close_cover_tilt(hass, entity_id=None): + """Close all or specified cover tilt.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_CLOSE_COVER_TILT, data) + + +def set_cover_tilt_position(hass, tilt_position, entity_id=None): + """Move to specific tilt position all or specified cover.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} + data[ATTR_TILT_POSITION] = tilt_position + hass.services.call(DOMAIN, SERVICE_SET_COVER_TILT_POSITION, data) + + +def stop_cover_tilt(hass, entity_id=None): + """Stop all or specified cover tilt.""" + data = {ATTR_ENTITY_ID: entity_id} if entity_id else None + hass.services.call(DOMAIN, SERVICE_STOP_COVER_TILT, data) + + +def setup(hass, config): + """Track states and offer events for covers.""" + component = EntityComponent( + _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_COVERS) + component.setup(config) + + def handle_cover_service(service): + """Handle calls to the cover services.""" + method = SERVICE_TO_METHOD.get(service.service) + params = service.data.copy() + params.pop(ATTR_ENTITY_ID, None) + + if method: + for cover in component.extract_from_service(service): + getattr(cover, method['method'])(**params) + + if cover.should_poll: + cover.update_ha_state(True) + + descriptions = load_yaml_config_file( + os.path.join(os.path.dirname(__file__), 'services.yaml')) + + for service_name in SERVICE_TO_METHOD: + schema = SERVICE_TO_METHOD[service_name].get( + 'schema', COVER_SERVICE_SCHEMA) + hass.services.register(DOMAIN, service_name, handle_cover_service, + descriptions.get(service_name), schema=schema) + return True + + +class CoverDevice(Entity): + """Representation a cover.""" + + # pylint: disable=no-self-use + @property + def current_cover_position(self): + """Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + return None + + @property + def current_cover_tilt_position(self): + """Return current position of cover tilt. + + None is unknown, 0 is closed, 100 is fully open. + """ + return None + + @property + def state(self): + """Return the state of the cover.""" + closed = self.is_closed + + if closed is None: + return STATE_UNKNOWN + + return STATE_CLOSED if closed else STATE_OPEN + + @property + def state_attributes(self): + """Return the state attributes.""" + data = { + ATTR_CURRENT_POSITION: self.current_cover_position + } + + current_tilt = self.current_cover_tilt_position + if current_tilt is not None: + data[ATTR_CURRENT_TILT_POSITION] = self.current_cover_tilt_position + + return data + + @property + def is_closed(self): + """Return if the cover is closed or not.""" + return NotImplementedError() + + def open_cover(self, **kwargs): + """Open the cover.""" + raise NotImplementedError() + + def close_cover(self, **kwargs): + """Close cover.""" + raise NotImplementedError() + + def set_cover_position(self, **kwargs): + """Move the cover to a specific position.""" + pass + + def stop_cover(self, **kwargs): + """Stop the cover.""" + pass + + def open_cover_tilt(self, **kwargs): + """Open the cover tilt.""" + pass + + def close_cover_tilt(self, **kwargs): + """Close the cover tilt.""" + pass + + def set_cover_tilt_position(self, **kwargs): + """Move the cover tilt to a specific position.""" + pass + + def stop_cover_tilt(self, **kwargs): + """Stop the cover.""" + pass diff --git a/homeassistant/components/cover/command_line.py b/homeassistant/components/cover/command_line.py new file mode 100644 index 00000000000..c2c8050f09f --- /dev/null +++ b/homeassistant/components/cover/command_line.py @@ -0,0 +1,128 @@ +""" +Support for command line covers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.command_line/ +""" +import logging +import subprocess + +from homeassistant.components.cover import CoverDevice +from homeassistant.const import CONF_VALUE_TEMPLATE +from homeassistant.helpers import template + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup cover controlled by shell commands.""" + covers = config.get('covers', {}) + devices = [] + + for dev_name, properties in covers.items(): + devices.append( + CommandCover( + hass, + properties.get('name', dev_name), + properties.get('opencmd', 'true'), + properties.get('closecmd', 'true'), + properties.get('stopcmd', 'true'), + properties.get('statecmd', False), + properties.get(CONF_VALUE_TEMPLATE, '{{ value }}'))) + add_devices_callback(devices) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class CommandCover(CoverDevice): + """Representation a command line cover.""" + + # pylint: disable=too-many-arguments + def __init__(self, hass, name, command_open, command_close, command_stop, + command_state, value_template): + """Initialize the cover.""" + self._hass = hass + self._name = name + self._state = None + self._command_open = command_open + self._command_close = command_close + self._command_stop = command_stop + self._command_state = command_state + self._value_template = value_template + + @staticmethod + def _move_cover(command): + """Execute the actual commands.""" + _LOGGER.info('Running command: %s', command) + + success = (subprocess.call(command, shell=True) == 0) + + if not success: + _LOGGER.error('Command failed: %s', command) + + return success + + @staticmethod + def _query_state_value(command): + """Execute state command for return value.""" + _LOGGER.info('Running state command: %s', command) + + try: + return_value = subprocess.check_output(command, shell=True) + return return_value.strip().decode('utf-8') + except subprocess.CalledProcessError: + _LOGGER.error('Command failed: %s', command) + + @property + def should_poll(self): + """Only poll if we have state command.""" + return self._command_state is not None + + @property + def name(self): + """Return the name of the cover.""" + return self._name + + @property + def is_closed(self): + """Return if the cover is closed.""" + if self.current_cover_position is not None: + if self.current_cover_position > 0: + return False + else: + return True + + @property + def current_cover_position(self): + """Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + return self._state + + def _query_state(self): + """Query for the state.""" + if not self._command_state: + _LOGGER.error('No state command specified') + return + return self._query_state_value(self._command_state) + + def update(self): + """Update device state.""" + if self._command_state: + payload = str(self._query_state()) + if self._value_template: + payload = template.render_with_possible_json_value( + self._hass, self._value_template, payload) + self._state = int(payload) + + def open_cover(self, **kwargs): + """Open the cover.""" + self._move_cover(self._command_open) + + def close_cover(self, **kwargs): + """Close the cover.""" + self._move_cover(self._command_close) + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self._move_cover(self._command_stop) diff --git a/homeassistant/components/cover/demo.py b/homeassistant/components/cover/demo.py new file mode 100644 index 00000000000..a863ad83a64 --- /dev/null +++ b/homeassistant/components/cover/demo.py @@ -0,0 +1,155 @@ +""" +Demo platform for the cover component. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/demo/ +""" +from homeassistant.components.cover import CoverDevice +from homeassistant.const import EVENT_TIME_CHANGED +from homeassistant.helpers.event import track_utc_time_change + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Demo covers.""" + add_devices([ + DemoCover(hass, 'Kitchen Window'), + DemoCover(hass, 'Hall Window', 10), + DemoCover(hass, 'Living Room Window', 70, 50), + ]) + + +class DemoCover(CoverDevice): + """Representation of a demo cover.""" + + # pylint: disable=no-self-use, too-many-instance-attributes + def __init__(self, hass, name, position=None, tilt_position=None): + """Initialize the cover.""" + self.hass = hass + self._name = name + self._position = position + self._set_position = None + self._set_tilt_position = None + self._tilt_position = tilt_position + self._closing = True + self._closing_tilt = True + self._listener_cover = None + self._listener_cover_tilt = None + + @property + def name(self): + """Return the name of the cover.""" + return self._name + + @property + def should_poll(self): + """No polling needed for a demo cover.""" + return False + + @property + def current_cover_position(self): + """Return the current position of the cover.""" + return self._position + + @property + def current_cover_tilt_position(self): + """Return the current tilt position of the cover.""" + return self._tilt_position + + def close_cover(self, **kwargs): + """Close the cover.""" + if self._position == 0: + return + + self._listen_cover() + self._closing = True + + def close_cover_tilt(self, **kwargs): + """Close the cover tilt.""" + if self._tilt_position == 0: + return + + self._listen_cover_tilt() + self._closing_tilt = True + + def open_cover(self, **kwargs): + """Open the cover.""" + if self._position == 100: + return + + self._listen_cover() + self._closing = False + + def open_cover_tilt(self, **kwargs): + """Open the cover tilt.""" + if self._tilt_position == 100: + return + + self._listen_cover_tilt() + self._closing_tilt = False + + def set_cover_position(self, position, **kwargs): + """Move the cover to a specific position.""" + self._set_position = round(position, -1) + if self._position == position: + return + self._listen_cover() + self._closing = position < self._position + + def set_cover_tilt_position(self, tilt_position, **kwargs): + """Move the cover til to a specific position.""" + self._set_tilt_position = round(tilt_position, -1) + if self._tilt_position == tilt_position: + return + self._listen_cover_tilt() + self._closing_tilt = tilt_position < self._tilt_position + + def stop_cover(self, **kwargs): + """Stop the cover.""" + if self._listener_cover is not None: + self.hass.bus.remove_listener(EVENT_TIME_CHANGED, + self._listener_cover) + self._listener_cover = None + self._set_position = None + + def stop_cover_tilt(self, **kwargs): + """Stop the cover tilt.""" + if self._listener_cover_tilt is not None: + self.hass.bus.remove_listener(EVENT_TIME_CHANGED, + self._listener_cover_tilt) + self._listener_cover_tilt = None + self._set_tilt_position = None + + def _listen_cover(self): + """Listen for changes in cover.""" + if self._listener_cover is None: + self._listener_cover = track_utc_time_change( + self.hass, self._time_changed_cover) + + def _time_changed_cover(self, now): + """Track time changes.""" + if self._closing: + self._position -= 10 + else: + self._position += 10 + + if self._position in (100, 0, self._set_position): + self.stop_cover() + self.update_ha_state() + + def _listen_cover_tilt(self): + """Listen for changes in cover tilt.""" + if self._listener_cover_tilt is None: + self._listener_cover_tilt = track_utc_time_change( + self.hass, self._time_changed_cover_tilt) + + def _time_changed_cover_tilt(self, now): + """Track time changes.""" + if self._closing_tilt: + self._tilt_position -= 10 + else: + self._tilt_position += 10 + + if self._tilt_position in (100, 0, self._set_tilt_position): + self.stop_cover_tilt() + + self.update_ha_state() diff --git a/homeassistant/components/cover/homematic.py b/homeassistant/components/cover/homematic.py new file mode 100644 index 00000000000..cab6b51e645 --- /dev/null +++ b/homeassistant/components/cover/homematic.py @@ -0,0 +1,101 @@ +""" +The homematic cover platform. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.homematic/ + +Important: For this platform to work the homematic component has to be +properly configured. +""" + +import logging +from homeassistant.const import STATE_UNKNOWN +from homeassistant.components.cover import CoverDevice,\ + ATTR_CURRENT_POSITION +import homeassistant.components.homematic as homematic + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['homematic'] + + +def setup_platform(hass, config, add_callback_devices, discovery_info=None): + """Setup the platform.""" + if discovery_info is None: + return + + return homematic.setup_hmdevice_discovery_helper(HMCover, + discovery_info, + add_callback_devices) + + +# pylint: disable=abstract-method +class HMCover(homematic.HMDevice, CoverDevice): + """Represents a Homematic Cover in Home Assistant.""" + + @property + def current_cover_position(self): + """ + Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + if self.available: + return int((1 - self._hm_get_state()) * 100) + return None + + def set_cover_position(self, **kwargs): + """Move the cover to a specific position.""" + if self.available: + if ATTR_CURRENT_POSITION in kwargs: + position = float(kwargs[ATTR_CURRENT_POSITION]) + position = min(100, max(0, position)) + level = (100 - position) / 100.0 + self._hmdevice.set_level(level, self._channel) + + @property + def is_closed(self): + """Return if the cover is closed.""" + if self.current_cover_position is not None: + if self.current_cover_position > 0: + return False + else: + return True + + def open_cover(self, **kwargs): + """Open the cover.""" + if self.available: + self._hmdevice.move_up(self._channel) + + def close_cover(self, **kwargs): + """Close the cover.""" + if self.available: + self._hmdevice.move_down(self._channel) + + def stop_cover(self, **kwargs): + """Stop the device if in motion.""" + if self.available: + self._hmdevice.stop(self._channel) + + def _check_hm_to_ha_object(self): + """Check if possible to use the HM Object as this HA type.""" + from pyhomematic.devicetypes.actors import Blind + + # Check compatibility from HMDevice + if not super()._check_hm_to_ha_object(): + return False + + # Check if the homematic device is correct for this HA device + if isinstance(self._hmdevice, Blind): + return True + + _LOGGER.critical("This %s can't be use as cover!", self._name) + return False + + def _init_data_struct(self): + """Generate a data dict (self._data) from hm metadata.""" + super()._init_data_struct() + + # Add state to data dict + self._state = "LEVEL" + self._data.update({self._state: STATE_UNKNOWN}) diff --git a/homeassistant/components/cover/mqtt.py b/homeassistant/components/cover/mqtt.py new file mode 100644 index 00000000000..dd6b10e244d --- /dev/null +++ b/homeassistant/components/cover/mqtt.py @@ -0,0 +1,167 @@ +""" +Support for MQTT cover devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.mqtt/ +""" +import logging + +import voluptuous as vol + +import homeassistant.components.mqtt as mqtt +from homeassistant.components.cover import CoverDevice +from homeassistant.const import ( + CONF_NAME, CONF_VALUE_TEMPLATE, CONF_OPTIMISTIC, STATE_OPEN, + STATE_CLOSED) +from homeassistant.components.mqtt import ( + CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN) +from homeassistant.helpers import template +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['mqtt'] + +CONF_PAYLOAD_OPEN = 'payload_open' +CONF_PAYLOAD_CLOSE = 'payload_close' +CONF_PAYLOAD_STOP = 'payload_stop' +CONF_STATE_OPEN = 'state_open' +CONF_STATE_CLOSED = 'state_closed' + +DEFAULT_NAME = "MQTT Cover" +DEFAULT_PAYLOAD_OPEN = "OPEN" +DEFAULT_PAYLOAD_CLOSE = "CLOSE" +DEFAULT_PAYLOAD_STOP = "STOP" +DEFAULT_OPTIMISTIC = False +DEFAULT_RETAIN = False + +PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PAYLOAD_OPEN, default=DEFAULT_PAYLOAD_OPEN): cv.string, + vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): cv.string, + vol.Optional(CONF_PAYLOAD_STOP, default=DEFAULT_PAYLOAD_STOP): cv.string, + vol.Optional(CONF_STATE_OPEN, default=STATE_OPEN): cv.string, + vol.Optional(CONF_STATE_CLOSED, default=STATE_CLOSED): cv.string, + vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean, + vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean, + +}) + + +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Add MQTT Cover.""" + add_devices_callback([MqttCover( + hass, + config[CONF_NAME], + config.get(CONF_STATE_TOPIC), + config[CONF_COMMAND_TOPIC], + config[CONF_QOS], + config[CONF_RETAIN], + config[CONF_STATE_OPEN], + config[CONF_STATE_CLOSED], + config[CONF_PAYLOAD_OPEN], + config[CONF_PAYLOAD_CLOSE], + config[CONF_PAYLOAD_STOP], + config[CONF_OPTIMISTIC], + config.get(CONF_VALUE_TEMPLATE) + )]) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class MqttCover(CoverDevice): + """Representation of a cover that can be controlled using MQTT.""" + + def __init__(self, hass, name, state_topic, command_topic, qos, + retain, state_open, state_closed, payload_open, payload_close, + payload_stop, optimistic, value_template): + """Initialize the cover.""" + self._position = None + self._state = None + self._hass = hass + self._name = name + self._state_topic = state_topic + self._command_topic = command_topic + self._qos = qos + self._payload_open = payload_open + self._payload_close = payload_close + self._payload_stop = payload_stop + self._state_open = state_open + self._state_closed = state_closed + self._retain = retain + self._optimistic = optimistic or state_topic is None + + def message_received(topic, payload, qos): + """A new MQTT message has been received.""" + if value_template is not None: + payload = template.render_with_possible_json_value( + hass, value_template, payload) + if payload == self._state_open: + self._state = False + self.update_ha_state() + elif payload == self._state_closed: + self._state = True + self.update_ha_state() + elif payload.isnumeric() and 0 <= int(payload) <= 100: + self._state = int(payload) + self._position = int(payload) + self.update_ha_state() + else: + _LOGGER.warning( + "Payload is not True or False or" + " integer(0-100) %s", payload) + if self._state_topic is None: + # Force into optimistic mode. + self._optimistic = True + else: + mqtt.subscribe(hass, self._state_topic, message_received, + self._qos) + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the cover.""" + return self._name + + @property + def is_closed(self): + """Return if the cover is closed.""" + if self.current_cover_position is not None: + if self.current_cover_position > 0: + return False + else: + return True + + @property + def current_cover_position(self): + """Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + return self._position + + def open_cover(self, **kwargs): + """Move the cover up.""" + mqtt.publish(self.hass, self._command_topic, self._payload_open, + self._qos, self._retain) + if self._optimistic: + # Optimistically assume that cover has changed state. + self._state = 100 + self.update_ha_state() + + def close_cover(self, **kwargs): + """Move the cover down.""" + mqtt.publish(self.hass, self._command_topic, self._payload_close, + self._qos, self._retain) + if self._optimistic: + # Optimistically assume that cover has changed state. + self._state = 0 + self.update_ha_state() + + def stop_cover(self, **kwargs): + """Stop the device.""" + mqtt.publish(self.hass, self._command_topic, self._payload_stop, + self._qos, self._retain) diff --git a/homeassistant/components/cover/rfxtrx.py b/homeassistant/components/cover/rfxtrx.py new file mode 100644 index 00000000000..d7ca03f5762 --- /dev/null +++ b/homeassistant/components/cover/rfxtrx.py @@ -0,0 +1,67 @@ +""" +Support for RFXtrx cover components. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/cover.rfxtrx/ +""" + +import homeassistant.components.rfxtrx as rfxtrx +from homeassistant.components.cover import CoverDevice + +DEPENDENCIES = ['rfxtrx'] + +PLATFORM_SCHEMA = rfxtrx.DEFAULT_SCHEMA + + +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup the RFXtrx cover.""" + import RFXtrx as rfxtrxmod + + # Add cover from config file + covers = rfxtrx.get_devices_from_config(config, + RfxtrxCover) + add_devices_callback(covers) + + def cover_update(event): + """Callback for cover updates from the RFXtrx gateway.""" + if not isinstance(event.device, rfxtrxmod.LightingDevice) or \ + event.device.known_to_be_dimmable or \ + not event.device.known_to_be_rollershutter: + return + + new_device = rfxtrx.get_new_device(event, config, RfxtrxCover) + if new_device: + add_devices_callback([new_device]) + + rfxtrx.apply_received_command(event) + + # Subscribe to main rfxtrx events + if cover_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS: + rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(cover_update) + + +# pylint: disable=abstract-method +class RfxtrxCover(rfxtrx.RfxtrxDevice, CoverDevice): + """Representation of an rfxtrx cover.""" + + @property + def should_poll(self): + """No polling available in rfxtrx cover.""" + return False + + @property + def is_closed(self): + """Return if the cover is closed.""" + return None + + def open_cover(self, **kwargs): + """Move the cover up.""" + self._send_command("roll_up") + + def close_cover(self, **kwargs): + """Move the cover down.""" + self._send_command("roll_down") + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self._send_command("stop_roll") diff --git a/homeassistant/components/cover/rpi_gpio.py b/homeassistant/components/cover/rpi_gpio.py new file mode 100644 index 00000000000..f712e1b17cc --- /dev/null +++ b/homeassistant/components/cover/rpi_gpio.py @@ -0,0 +1,98 @@ +""" +Support for building a Raspberry Pi cover in HA. + +Instructions for building the controller can be found here +https://github.com/andrewshilliday/garage-door-controller + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.rpi_gpio/ +""" + +import logging +from time import sleep +import voluptuous as vol + +from homeassistant.components.cover import CoverDevice +import homeassistant.components.rpi_gpio as rpi_gpio +import homeassistant.helpers.config_validation as cv + +DEPENDENCIES = ['rpi_gpio'] + +_LOGGER = logging.getLogger(__name__) + +_COVERS_SCHEMA = vol.All( + cv.ensure_list, + [ + vol.Schema({ + 'name': str, + 'relay_pin': int, + 'state_pin': int, + }) + ] +) +PLATFORM_SCHEMA = vol.Schema({ + 'platform': str, + vol.Required('covers'): _COVERS_SCHEMA, +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the cover platform.""" + covers = [] + covers_conf = config.get('covers') + + for cover in covers_conf: + covers.append(RPiGPIOCover(cover['name'], cover['relay_pin'], + cover['state_pin'])) + add_devices(covers) + + +# pylint: disable=abstract-method +class RPiGPIOCover(CoverDevice): + """Representation of a Raspberry cover.""" + + def __init__(self, name, relay_pin, state_pin): + """Initialize the cover.""" + self._name = name + self._state = False + self._relay_pin = relay_pin + self._state_pin = state_pin + rpi_gpio.setup_output(self._relay_pin) + rpi_gpio.setup_input(self._state_pin, 'UP') + rpi_gpio.write_output(self._relay_pin, True) + + @property + def unique_id(self): + """Return the ID of this cover.""" + return "{}.{}".format(self.__class__, self._name) + + @property + def name(self): + """Return the name of the cover if any.""" + return self._name + + def update(self): + """Update the state of the cover.""" + self._state = rpi_gpio.read_input(self._state_pin) + + @property + def is_closed(self): + """Return true if cover is closed.""" + return self._state + + def _trigger(self): + """Trigger the cover.""" + rpi_gpio.write_output(self._relay_pin, False) + sleep(0.2) + rpi_gpio.write_output(self._relay_pin, True) + + def close_cover(self): + """Close the cover.""" + if not self.is_closed: + self._trigger() + + def open_cover(self): + """Open the cover.""" + if self.is_closed: + self._trigger() diff --git a/homeassistant/components/cover/scsgate.py b/homeassistant/components/cover/scsgate.py new file mode 100644 index 00000000000..18692534e90 --- /dev/null +++ b/homeassistant/components/cover/scsgate.py @@ -0,0 +1,96 @@ +""" +Allow to configure a SCSGate cover. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.scsgate/ +""" +import logging + +import homeassistant.components.scsgate as scsgate +from homeassistant.components.cover import CoverDevice +from homeassistant.const import CONF_NAME + +DEPENDENCIES = ['scsgate'] +SCS_ID = 'scs_id' + + +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """Setup the SCSGate cover.""" + devices = config.get('devices') + covers = [] + logger = logging.getLogger(__name__) + + if devices: + for _, entity_info in devices.items(): + if entity_info[SCS_ID] in scsgate.SCSGATE.devices: + continue + + logger.info("Adding %s scsgate.cover", entity_info[CONF_NAME]) + + name = entity_info[CONF_NAME] + scs_id = entity_info[SCS_ID] + cover = SCSGateCover( + name=name, + scs_id=scs_id, + logger=logger) + scsgate.SCSGATE.add_device(cover) + covers.append(cover) + + add_devices_callback(covers) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class SCSGateCover(CoverDevice): + """Representation of SCSGate cover.""" + + def __init__(self, scs_id, name, logger): + """Initialize the cover.""" + self._scs_id = scs_id + self._name = name + self._logger = logger + + @property + def scs_id(self): + """Return the SCSGate ID.""" + return self._scs_id + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the cover.""" + return self._name + + @property + def is_closed(self): + """Return if the cover is closed.""" + return None + + def open_cover(self, **kwargs): + """Move the cover.""" + from scsgate.tasks import RaiseRollerShutterTask + + scsgate.SCSGATE.append_task( + RaiseRollerShutterTask(target=self._scs_id)) + + def close_cover(self, **kwargs): + """Move the cover down.""" + from scsgate.tasks import LowerRollerShutterTask + + scsgate.SCSGATE.append_task( + LowerRollerShutterTask(target=self._scs_id)) + + def stop_cover(self, **kwargs): + """Stop the cover.""" + from scsgate.tasks import HaltRollerShutterTask + + scsgate.SCSGATE.append_task(HaltRollerShutterTask(target=self._scs_id)) + + def process_event(self, message): + """Handle a SCSGate message related with this cover.""" + self._logger.debug( + "Rollershutter %s, got message %s", + self._scs_id, message.toggled) diff --git a/homeassistant/components/cover/services.yaml b/homeassistant/components/cover/services.yaml new file mode 100644 index 00000000000..02765ca9ab8 --- /dev/null +++ b/homeassistant/components/cover/services.yaml @@ -0,0 +1,71 @@ +open_cover: + description: Open all or specified cover + + fields: + entity_id: + description: Name(s) of cover(s) to open + example: 'cover.living_room' + +close_cover: + description: Close all or specified cover + + fields: + entity_id: + description: Name(s) of cover(s) to close + example: 'cover.living_room' + +set_cover_position: + description: Move to specific position all or specified cover + + fields: + entity_id: + description: Name(s) of cover(s) to set cover position + example: 'cover.living_room' + + position: + description: Position of the cover (0 to 100) + example: 30 + +stop_cover: + description: Stop all or specified cover + + fields: + entity_id: + description: Name(s) of cover(s) to stop + example: 'cover.living_room' + +open_cover_tilt: + description: Open all or specified cover tilt + + fields: + entity_id: + description: Name(s) of cover(s) tilt to open + example: 'cover.living_room' + +close_cover_tilt: + description: Close all or specified cover tilt + + fields: + entity_id: + description: Name(s) of cover(s) to close tilt + example: 'cover.living_room' + +set_cover_tilt_position: + description: Move to specific position all or specified cover tilt + + fields: + entity_id: + description: Name(s) of cover(s) to set cover tilt position + example: 'cover.living_room' + + position: + description: Position of the cover (0 to 100) + example: 30 + +stop_cover_tilt: + description: Stop all or specified cover + + fields: + entity_id: + description: Name(s) of cover(s) to stop + example: 'cover.living_room' diff --git a/homeassistant/components/cover/wink.py b/homeassistant/components/cover/wink.py new file mode 100644 index 00000000000..9b76e234303 --- /dev/null +++ b/homeassistant/components/cover/wink.py @@ -0,0 +1,64 @@ +""" +Support for Wink Covers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.wink/ +""" +import logging + +from homeassistant.components.cover import CoverDevice +from homeassistant.components.wink import WinkDevice +from homeassistant.const import CONF_ACCESS_TOKEN + +REQUIREMENTS = ['python-wink==0.7.13', 'pubnub==3.8.2'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Wink cover platform.""" + import pywink + + if discovery_info is None: + token = config.get(CONF_ACCESS_TOKEN) + + if token is None: + logging.getLogger(__name__).error( + "Missing wink access_token. " + "Get one at https://winkbearertoken.appspot.com/") + return + + pywink.set_bearer_token(token) + + add_devices(WinkCoverDevice(shade) for shade, door in + pywink.get_shades()) + + +class WinkCoverDevice(WinkDevice, CoverDevice): + """Representation of a Wink covers.""" + + def __init__(self, wink): + """Initialize the cover.""" + WinkDevice.__init__(self, wink) + + @property + def should_poll(self): + """Wink Shades don't track their position.""" + return False + + def close_cover(self): + """Close the shade.""" + self.wink.set_state(0) + + def open_cover(self): + """Open the shade.""" + self.wink.set_state(1) + + @property + def is_closed(self): + """Return if the cover is closed.""" + state = self.wink.state() + if state == 0: + return True + elif state == 1: + return False + else: + return None diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py new file mode 100644 index 00000000000..83d55001fe2 --- /dev/null +++ b/homeassistant/components/cover/zwave.py @@ -0,0 +1,184 @@ +""" +Support for Zwave cover components. + +For more details about this platform, please refer to the documentation +https://home-assistant.io/components/cover.zwave/ +""" +# Because we do not compile openzwave on CI +# pylint: disable=import-error +import logging +from homeassistant.components.cover import DOMAIN +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) +WORKAROUND = 'workaround' + +DEVICE_MAPPINGS = { + SOMFY_ZRTSI_CONTROLLER: WORKAROUND +} + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Find and return Z-Wave covers.""" + 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]] + + if (value.command_class == zwave.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: + return + value.set_change_verified(False) + add_devices([ZwaveGarageDoor(value)]) + else: + return + + +class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): + """Representation of an Zwave roller shutter.""" + + def __init__(self, value): + """Initialize the zwave rollershutter.""" + import libopenzwave + from openzwave.network import ZWaveNetwork + from pydispatch import dispatcher + ZWaveDeviceEntity.__init__(self, value, DOMAIN) + self._lozwmgr = libopenzwave.PyManager() + self._lozwmgr.create() + self._node = value.node + self._current_position = None + self._workaround = None + dispatcher.connect( + self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) + if (value.node.manufacturer_id.strip() and + value.node.product_id.strip()): + specific_sensor_key = (int(value.node.manufacturer_id, 16), + int(value.node.product_type, 16)) + + if specific_sensor_key in DEVICE_MAPPINGS: + if DEVICE_MAPPINGS[specific_sensor_key] == WORKAROUND: + _LOGGER.debug("Controller without positioning feedback") + self._workaround = 1 + + def value_changed(self, value): + """Called when a value has changed on the network.""" + if self._value.value_id == value.value_id or \ + self._value.node == value.node: + self.update_properties() + self.update_ha_state() + _LOGGER.debug("Value changed on network %s", value) + + def update_properties(self): + """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': + self._current_position = value.data + + @property + def is_closed(self): + """Return if the cover is closed.""" + if self.current_cover_position > 0: + return False + else: + return True + + @property + def current_cover_position(self): + """Return the current position of Zwave roller shutter.""" + if not self._workaround: + if self._current_position is not None: + if self._current_position <= 5: + return 0 + elif self._current_position >= 95: + return 100 + else: + return self._current_position + + 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': + 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': + self._lozwmgr.pressButton(value.value_id) + break + + def set_cover_position(self, position, **kwargs): + """Move the roller shutter to a specific position.""" + self._node.set_dimmer(self._value.value_id, 100 - position) + + 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': + self._lozwmgr.releaseButton(value.value_id) + break + + +class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice): + """Representation of an Zwave garage door device.""" + + def __init__(self, value): + """Initialize the zwave garage door.""" + from openzwave.network import ZWaveNetwork + from pydispatch import dispatcher + ZWaveDeviceEntity.__init__(self, value, DOMAIN) + self._state = value.data + dispatcher.connect( + self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) + + def value_changed(self, value): + """Called when a value has changed on the network.""" + if self._value.value_id == value.value_id: + self._state = value.data + self.update_ha_state() + _LOGGER.debug("Value changed on network %s", value) + + @property + def is_closed(self): + """Return the current position of Zwave garage door.""" + return not self._state + + def close_cover(self): + """Close the garage door.""" + self._value.data = False + + def open_cover(self): + """Open the garage door.""" + self._value.data = True diff --git a/homeassistant/components/garage_door/__init__.py b/homeassistant/components/garage_door/__init__.py index 37e422d0f12..c5576b1da84 100644 --- a/homeassistant/components/garage_door/__init__.py +++ b/homeassistant/components/garage_door/__init__.py @@ -54,6 +54,9 @@ def open_door(hass, entity_id=None): def setup(hass, config): """Track states and offer events for garage door.""" + _LOGGER.warning('This component has been deprecated in favour of the ' + '"cover" component and will be removed in the future.' + ' Please upgrade.') component = EntityComponent( _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_GARAGE_DOORS) component.setup(config) diff --git a/homeassistant/components/rollershutter/__init__.py b/homeassistant/components/rollershutter/__init__.py index 7d8b8235ed6..3928eb384d8 100644 --- a/homeassistant/components/rollershutter/__init__.py +++ b/homeassistant/components/rollershutter/__init__.py @@ -77,6 +77,9 @@ def stop(hass, entity_id=None): def setup(hass, config): """Track states and offer events for roller shutters.""" + _LOGGER.warning('This component has been deprecated in favour of the ' + '"cover" component and will be removed in the future.' + ' Please upgrade.') component = EntityComponent( _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_ROLLERSHUTTERS) component.setup(config) diff --git a/homeassistant/components/zwave.py b/homeassistant/components/zwave.py index fa0cf410942..eb1d048244b 100644 --- a/homeassistant/components/zwave.py +++ b/homeassistant/components/zwave.py @@ -162,22 +162,19 @@ DISCOVERY_COMPONENTS = [ [COMMAND_CLASS_DOOR_LOCK], TYPE_BOOL, GENRE_USER), - ('rollershutter', - [GENERIC_COMMAND_CLASS_MULTILEVEL_SWITCH], + ('cover', + [GENERIC_COMMAND_CLASS_MULTILEVEL_SWITCH, + GENERIC_COMMAND_CLASS_ENTRY_CONTROL], [SPECIFIC_DEVICE_CLASS_MOTOR_CONTROL_CLASS_A, SPECIFIC_DEVICE_CLASS_MOTOR_CONTROL_CLASS_B, SPECIFIC_DEVICE_CLASS_MOTOR_CONTROL_CLASS_C, - SPECIFIC_DEVICE_CLASS_MULTIPOSITION_MOTOR], - [COMMAND_CLASS_WHATEVER], - TYPE_WHATEVER, - GENRE_USER), - ('garage_door', - [GENERIC_COMMAND_CLASS_ENTRY_CONTROL], - [SPECIFIC_DEVICE_CLASS_SECURE_BARRIER_ADD_ON, + SPECIFIC_DEVICE_CLASS_MULTIPOSITION_MOTOR, + SPECIFIC_DEVICE_CLASS_SECURE_BARRIER_ADD_ON, SPECIFIC_DEVICE_CLASS_SECURE_DOOR], [COMMAND_CLASS_SWITCH_BINARY, - COMMAND_CLASS_BARRIER_OPERATOR], - TYPE_BOOL, + COMMAND_CLASS_BARRIER_OPERATOR, + COMMAND_CLASS_SWITCH_MULTILEVEL], + TYPE_WHATEVER, GENRE_USER), ('climate', [GENERIC_COMMAND_CLASS_THERMOSTAT], diff --git a/homeassistant/const.py b/homeassistant/const.py index e2e76d8b86e..4ccaa3cf6f7 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -233,6 +233,15 @@ SERVICE_UNLOCK = 'unlock' SERVICE_OPEN = 'open' SERVICE_CLOSE = 'close' +SERVICE_CLOSE_COVER = 'close_cover' +SERVICE_CLOSE_COVER_TILT = 'close_cover_tilt' +SERVICE_OPEN_COVER = 'open_cover' +SERVICE_OPEN_COVER_TILT = 'open_cover_tilt' +SERVICE_SET_COVER_POSITION = 'set_cover_position' +SERVICE_SET_COVER_TILT_POSITION = 'set_cover_tilt_position' +SERVICE_STOP_COVER = 'stop' +SERVICE_STOP_COVER_TILT = 'stop_cover_tilt' + SERVICE_MOVE_UP = 'move_up' SERVICE_MOVE_DOWN = 'move_down' SERVICE_MOVE_POSITION = 'move_position' diff --git a/requirements_all.txt b/requirements_all.txt index c974f37799d..ccc638561e0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -273,6 +273,7 @@ psutil==4.3.0 # homeassistant.components.wink # homeassistant.components.binary_sensor.wink +# homeassistant.components.cover.wink # homeassistant.components.garage_door.wink # homeassistant.components.light.wink # homeassistant.components.lock.wink @@ -382,6 +383,7 @@ python-twitch==1.3.0 # homeassistant.components.wink # homeassistant.components.binary_sensor.wink +# homeassistant.components.cover.wink # homeassistant.components.garage_door.wink # homeassistant.components.light.wink # homeassistant.components.lock.wink diff --git a/tests/components/cover/test_command_line.py b/tests/components/cover/test_command_line.py new file mode 100644 index 00000000000..bab0137f4f8 --- /dev/null +++ b/tests/components/cover/test_command_line.py @@ -0,0 +1,84 @@ +"""The tests the cover command line platform.""" + +import os +import tempfile +import unittest +from unittest import mock + +import homeassistant.core as ha +import homeassistant.components.cover as cover +from homeassistant.components.cover import ( + command_line as cmd_rs) + + +class TestCommandCover(unittest.TestCase): + """Test the cover command line platform.""" + + def setup_method(self, method): + """Setup things to be run when tests are started.""" + self.hass = ha.HomeAssistant() + self.hass.config.latitude = 32.87336 + self.hass.config.longitude = 117.22743 + self.rs = cmd_rs.CommandCover(self.hass, 'foo', + 'cmd_open', 'cmd_close', + 'cmd_stop', 'cmd_state', + None) # FIXME + + def teardown_method(self, method): + """Stop down everything that was started.""" + self.hass.stop() + + def test_should_poll(self): + """Test the setting of polling.""" + self.assertTrue(self.rs.should_poll) + self.rs._command_state = None + self.assertFalse(self.rs.should_poll) + + def test_query_state_value(self): + """Test with state value.""" + with mock.patch('subprocess.check_output') as mock_run: + mock_run.return_value = b' foo bar ' + result = self.rs._query_state_value('runme') + self.assertEqual('foo bar', result) + mock_run.assert_called_once_with('runme', shell=True) + + def test_state_value(self): + """Test with state value.""" + with tempfile.TemporaryDirectory() as tempdirname: + path = os.path.join(tempdirname, 'cover_status') + test_cover = { + 'statecmd': 'cat {}'.format(path), + 'opencmd': 'echo 1 > {}'.format(path), + 'closecmd': 'echo 1 > {}'.format(path), + 'stopcmd': 'echo 0 > {}'.format(path), + 'value_template': '{{ value }}' + } + self.assertTrue(cover.setup(self.hass, { + 'cover': { + 'platform': 'command_line', + 'covers': { + 'test': test_cover + } + } + })) + + state = self.hass.states.get('cover.test') + self.assertEqual('unknown', state.state) + + cover.open_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual('open', state.state) + + cover.close_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual('open', state.state) + + cover.stop_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual('closed', state.state) diff --git a/tests/components/cover/test_demo.py b/tests/components/cover/test_demo.py new file mode 100644 index 00000000000..d7431f8fcbb --- /dev/null +++ b/tests/components/cover/test_demo.py @@ -0,0 +1,138 @@ +"""The tests for the Demo cover platform.""" +import unittest +from datetime import timedelta +import homeassistant.util.dt as dt_util + +from homeassistant.components import cover +from tests.common import get_test_home_assistant, fire_time_changed + +ENTITY_COVER = 'cover.living_room_window' + + +class TestCoverDemo(unittest.TestCase): + """Test the Demo cover.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.assertTrue(cover.setup(self.hass, {'cover': { + 'platform': 'demo', + }})) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_close_cover(self): + """Test closing the cover.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(70, state.attributes.get('current_position')) + cover.close_cover(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(7): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(0, state.attributes.get('current_position')) + + def test_open_cover(self): + """Test opening the cover.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(70, state.attributes.get('current_position')) + cover.open_cover(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(7): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(100, state.attributes.get('current_position')) + + def test_set_cover_position(self): + """Test moving the cover to a specific position.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(70, state.attributes.get('current_position')) + cover.set_cover_position(self.hass, 10, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(6): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(10, state.attributes.get('current_position')) + + def test_stop_cover(self): + """Test stopping the cover.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(70, state.attributes.get('current_position')) + cover.open_cover(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + cover.stop_cover(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + fire_time_changed(self.hass, future) + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(80, state.attributes.get('current_position')) + + def test_close_cover_tilt(self): + """Test closing the cover tilt.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(50, state.attributes.get('current_tilt_position')) + cover.close_cover_tilt(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(7): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(0, state.attributes.get('current_tilt_position')) + + def test_open_cover_tilt(self): + """Test opening the cover tilt.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(50, state.attributes.get('current_tilt_position')) + cover.open_cover_tilt(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(7): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(100, state.attributes.get('current_tilt_position')) + + def test_set_cover_tilt_position(self): + """Test moving the cover til to a specific position.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(50, state.attributes.get('current_tilt_position')) + cover.set_cover_tilt_position(self.hass, 90, ENTITY_COVER) + self.hass.pool.block_till_done() + for _ in range(7): + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(90, state.attributes.get('current_tilt_position')) + + def test_stop_cover_tilt(self): + """Test stopping the cover tilt.""" + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(50, state.attributes.get('current_tilt_position')) + cover.close_cover_tilt(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + future = dt_util.utcnow() + timedelta(seconds=1) + fire_time_changed(self.hass, future) + self.hass.pool.block_till_done() + cover.stop_cover_tilt(self.hass, ENTITY_COVER) + self.hass.pool.block_till_done() + fire_time_changed(self.hass, future) + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(40, state.attributes.get('current_tilt_position')) diff --git a/tests/components/cover/test_mqtt.py b/tests/components/cover/test_mqtt.py new file mode 100644 index 00000000000..a1b9f0b92fc --- /dev/null +++ b/tests/components/cover/test_mqtt.py @@ -0,0 +1,174 @@ +"""The tests for the MQTT cover platform.""" +import unittest + +from homeassistant.bootstrap import _setup_component +from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN +import homeassistant.components.cover as cover +from tests.common import mock_mqtt_component, fire_mqtt_message + +from tests.common import get_test_home_assistant + + +class TestCoverMQTT(unittest.TestCase): + """Test the MQTT cover.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.mock_publish = mock_mqtt_component(self.hass) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_controlling_state_via_topic(self): + """Test the controlling state via topic.""" + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 0, + 'payload_open': 'OPEN', + 'payload_close': 'CLOSE', + 'payload_stop': 'STOP' + } + }) + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + fire_mqtt_message(self.hass, 'state-topic', '0') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_CLOSED, state.state) + + fire_mqtt_message(self.hass, 'state-topic', '50') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_OPEN, state.state) + + fire_mqtt_message(self.hass, 'state-topic', '100') + self.hass.pool.block_till_done() + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_OPEN, state.state) + + def test_send_open_cover_command(self): + """Test the sending of open_cover.""" + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 2 + } + }) + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + cover.open_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + self.assertEqual(('command-topic', 'OPEN', 2, False), + self.mock_publish.mock_calls[-1][1]) + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + def test_send_close_cover_command(self): + """Test the sending of close_cover.""" + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 2 + } + }) + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + cover.close_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + self.assertEqual(('command-topic', 'CLOSE', 2, False), + self.mock_publish.mock_calls[-1][1]) + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + def test_send_stop__cover_command(self): + """Test the sending of stop_cover.""" + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'qos': 2 + } + }) + + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + cover.stop_cover(self.hass, 'cover.test') + self.hass.pool.block_till_done() + + self.assertEqual(('command-topic', 'STOP', 2, False), + self.mock_publish.mock_calls[-1][1]) + state = self.hass.states.get('cover.test') + self.assertEqual(STATE_UNKNOWN, state.state) + + def test_state_attributes_current_cover_position(self): + """Test the current cover position.""" + self.hass.config.components = ['mqtt'] + assert _setup_component(self.hass, cover.DOMAIN, { + cover.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'payload_open': 'OPEN', + 'payload_close': 'CLOSE', + 'payload_stop': 'STOP' + } + }) + + state_attributes_dict = self.hass.states.get( + 'cover.test').attributes + self.assertTrue('current_position' in state_attributes_dict) + + fire_mqtt_message(self.hass, 'state-topic', '0') + self.hass.pool.block_till_done() + current_cover_position = self.hass.states.get( + 'cover.test').attributes['current_position'] + self.assertEqual(0, current_cover_position) + + fire_mqtt_message(self.hass, 'state-topic', '50') + self.hass.pool.block_till_done() + current_cover_position = self.hass.states.get( + 'cover.test').attributes['current_position'] + self.assertEqual(50, current_cover_position) + + fire_mqtt_message(self.hass, 'state-topic', '101') + self.hass.pool.block_till_done() + current_cover_position = self.hass.states.get( + 'cover.test').attributes['current_position'] + self.assertEqual(50, current_cover_position) + + fire_mqtt_message(self.hass, 'state-topic', 'non-numeric') + self.hass.pool.block_till_done() + current_cover_position = self.hass.states.get( + 'cover.test').attributes['current_position'] + self.assertEqual(50, current_cover_position) diff --git a/tests/components/cover/test_rfxtrx.py b/tests/components/cover/test_rfxtrx.py new file mode 100644 index 00000000000..96fecff2ee2 --- /dev/null +++ b/tests/components/cover/test_rfxtrx.py @@ -0,0 +1,216 @@ +"""The tests for the Rfxtrx cover platform.""" +import unittest + +from homeassistant.bootstrap import _setup_component +from homeassistant.components import rfxtrx as rfxtrx_core + +from tests.common import get_test_home_assistant + + +class TestCoverRfxtrx(unittest.TestCase): + """Test the Rfxtrx cover platform.""" + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant(0) + self.hass.config.components = ['rfxtrx'] + + def tearDown(self): + """Stop everything that was started.""" + rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS = [] + rfxtrx_core.RFX_DEVICES = {} + if rfxtrx_core.RFXOBJECT: + rfxtrx_core.RFXOBJECT.close_connection() + self.hass.stop() + + def test_valid_config(self): + """Test configuration.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'devices': + {'0b1100cd0213c7f210010f51': { + 'name': 'Test', + rfxtrx_core.ATTR_FIREEVENT: True} + }}})) + + def test_invalid_config_capital_letters(self): + """Test configuration.""" + self.assertFalse(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'devices': + {'2FF7f216': { + 'name': 'Test', + 'packetid': '0b1100cd0213c7f210010f51', + 'signal_repetitions': 3} + }}})) + + def test_invalid_config_extra_key(self): + """Test configuration.""" + self.assertFalse(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'invalid_key': 'afda', + 'devices': + {'213c7f216': { + 'name': 'Test', + 'packetid': '0b1100cd0213c7f210010f51', + rfxtrx_core.ATTR_FIREEVENT: True} + }}})) + + def test_invalid_config_capital_packetid(self): + """Test configuration.""" + self.assertFalse(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'devices': + {'213c7f216': { + 'name': 'Test', + 'packetid': 'AA1100cd0213c7f210010f51', + rfxtrx_core.ATTR_FIREEVENT: True} + }}})) + + def test_invalid_config_missing_packetid(self): + """Test configuration.""" + self.assertFalse(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'devices': + {'213c7f216': { + 'name': 'Test', + rfxtrx_core.ATTR_FIREEVENT: True} + }}})) + + def test_default_config(self): + """Test with 0 cover.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'devices': {}}})) + self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES)) + + def test_one_cover(self): + """Test with 1 cover.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'devices': + {'0b1400cd0213c7f210010f51': { + 'name': 'Test' + }}}})) + + import RFXtrx as rfxtrxmod + rfxtrx_core.RFXOBJECT =\ + rfxtrxmod.Core("", transport_protocol=rfxtrxmod.DummyTransport) + + self.assertEqual(1, len(rfxtrx_core.RFX_DEVICES)) + for id in rfxtrx_core.RFX_DEVICES: + entity = rfxtrx_core.RFX_DEVICES[id] + self.assertEqual(entity.signal_repetitions, 1) + self.assertFalse(entity.should_fire_event) + self.assertFalse(entity.should_poll) + entity.open_cover() + entity.close_cover() + entity.stop_cover() + + def test_several_covers(self): + """Test with 3 covers.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'signal_repetitions': 3, + 'devices': + {'0b1100cd0213c7f230010f71': { + 'name': 'Test'}, + '0b1100100118cdea02010f70': { + 'name': 'Bath'}, + '0b1100101118cdea02010f70': { + 'name': 'Living'} + }}})) + + self.assertEqual(3, len(rfxtrx_core.RFX_DEVICES)) + device_num = 0 + for id in rfxtrx_core.RFX_DEVICES: + entity = rfxtrx_core.RFX_DEVICES[id] + self.assertEqual(entity.signal_repetitions, 3) + if entity.name == 'Living': + device_num = device_num + 1 + elif entity.name == 'Bath': + device_num = device_num + 1 + elif entity.name == 'Test': + device_num = device_num + 1 + + self.assertEqual(3, device_num) + + def test_discover_covers(self): + """Test with discovery of covers.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': True, + 'devices': {}}})) + + event = rfxtrx_core.get_rfx_object('0a140002f38cae010f0070') + event.data = bytearray([0x0A, 0x14, 0x00, 0x02, 0xF3, 0x8C, + 0xAE, 0x01, 0x0F, 0x00, 0x70]) + + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(1, len(rfxtrx_core.RFX_DEVICES)) + + event = rfxtrx_core.get_rfx_object('0a1400adf394ab020e0060') + event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94, + 0xAB, 0x02, 0x0E, 0x00, 0x60]) + + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES)) + + # Trying to add a sensor + event = rfxtrx_core.get_rfx_object('0a52085e070100b31b0279') + event.data = bytearray(b'\nR\x08^\x07\x01\x00\xb3\x1b\x02y') + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES)) + + # Trying to add a light + event = rfxtrx_core.get_rfx_object('0b1100100118cdea02010f70') + event.data = bytearray([0x0b, 0x11, 0x11, 0x10, 0x01, 0x18, + 0xcd, 0xea, 0x01, 0x02, 0x0f, 0x70]) + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(2, len(rfxtrx_core.RFX_DEVICES)) + + def test_discover_cover_noautoadd(self): + """Test with discovery of cover when auto add is False.""" + self.assertTrue(_setup_component(self.hass, 'cover', { + 'cover': {'platform': 'rfxtrx', + 'automatic_add': False, + 'devices': {}}})) + + event = rfxtrx_core.get_rfx_object('0a1400adf394ab010d0060') + event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94, + 0xAB, 0x01, 0x0D, 0x00, 0x60]) + + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES)) + + event = rfxtrx_core.get_rfx_object('0a1400adf394ab020e0060') + event.data = bytearray([0x0A, 0x14, 0x00, 0xAD, 0xF3, 0x94, + 0xAB, 0x02, 0x0E, 0x00, 0x60]) + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES)) + + # Trying to add a sensor + event = rfxtrx_core.get_rfx_object('0a52085e070100b31b0279') + event.data = bytearray(b'\nR\x08^\x07\x01\x00\xb3\x1b\x02y') + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES)) + + # Trying to add a light + event = rfxtrx_core.get_rfx_object('0b1100100118cdea02010f70') + event.data = bytearray([0x0b, 0x11, 0x11, 0x10, 0x01, + 0x18, 0xcd, 0xea, 0x01, 0x02, 0x0f, 0x70]) + for evt_sub in rfxtrx_core.RECEIVED_EVT_SUBSCRIBERS: + evt_sub(event) + self.assertEqual(0, len(rfxtrx_core.RFX_DEVICES)) From 6f27d58188ce908ea6f04e0f9cd7887c1201b614 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 24 Aug 2016 03:58:59 +0200 Subject: [PATCH 148/193] Use voluptuous for Splunk (#2931) * Migrate to voluptuous * Update tests --- homeassistant/components/splunk.py | 50 ++++++++++++++---------------- tests/components/test_splunk.py | 13 ++++++-- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/splunk.py b/homeassistant/components/splunk.py index 9a5f6e385eb..2ae2842bceb 100644 --- a/homeassistant/components/splunk.py +++ b/homeassistant/components/splunk.py @@ -1,8 +1,6 @@ """ Support to send data to an Splunk instance. -Uses the HTTP Event Collector. - For more details about this component, please refer to the documentation at https://home-assistant.io/components/splunk/ """ @@ -10,47 +8,47 @@ import json import logging import requests +import voluptuous as vol -import homeassistant.util as util -from homeassistant.const import EVENT_STATE_CHANGED +from homeassistant.const import ( + CONF_HOST, CONF_PORT, CONF_SSL, CONF_TOKEN, EVENT_STATE_CHANGED) from homeassistant.helpers import state as state_helper -from homeassistant.helpers import validate_config +import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -DOMAIN = "splunk" -DEPENDENCIES = [] +DOMAIN = 'splunk' DEFAULT_HOST = 'localhost' -DEFAULT_PORT = '8088' +DEFAULT_PORT = 8088 DEFAULT_SSL = False -CONF_HOST = 'host' -CONF_PORT = 'port' -CONF_TOKEN = 'token' -CONF_SSL = 'SSL' +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_TOKEN): cv.string, + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_SSL, default=False): cv.boolean, + }), +}, extra=vol.ALLOW_EXTRA) def setup(hass, config): """Setup the Splunk component.""" - if not validate_config(config, {DOMAIN: ['token']}, _LOGGER): - _LOGGER.error("You must include the token for your HTTP " - "Event Collector input in Splunk.") - return False - conf = config[DOMAIN] + host = conf.get(CONF_HOST) + port = conf.get(CONF_PORT) + token = conf.get(CONF_TOKEN) + use_ssl = conf.get(CONF_SSL) - host = conf[CONF_HOST] - port = util.convert(conf.get(CONF_PORT), int, DEFAULT_PORT) - token = util.convert(conf.get(CONF_TOKEN), str) - use_ssl = util.convert(conf.get(CONF_SSL), bool, DEFAULT_SSL) if use_ssl: - uri_scheme = "https://" + uri_scheme = 'https://' else: - uri_scheme = "http://" - event_collector = uri_scheme + host + ":" + str(port) + \ - "/services/collector/event" - headers = {'Authorization': 'Splunk ' + token} + uri_scheme = 'http://' + + event_collector = '{}{}:{}/services/collector/event'.format( + uri_scheme, host, port) + headers = {'Authorization': 'Splunk {}'.format(token)} def splunk_event_listener(event): """Listen for new messages on the bus and sends them to Splunk.""" diff --git a/tests/components/test_splunk.py b/tests/components/test_splunk.py index e4e9cf96ee0..4b7dd5f0732 100644 --- a/tests/components/test_splunk.py +++ b/tests/components/test_splunk.py @@ -19,6 +19,7 @@ class TestSplunk(unittest.TestCase): 'use_ssl': 'False', } } + hass = mock.MagicMock() self.assertTrue(splunk.setup(hass, config)) self.assertTrue(hass.bus.listen.called) @@ -33,6 +34,7 @@ class TestSplunk(unittest.TestCase): 'token': 'secret', } } + hass = mock.MagicMock() self.assertTrue(splunk.setup(hass, config)) self.assertTrue(hass.bus.listen.called) @@ -48,8 +50,10 @@ class TestSplunk(unittest.TestCase): 'splunk': { 'host': 'host', 'token': 'secret', + 'port': 8088, } } + self.hass = mock.MagicMock() splunk.setup(self.hass, config) self.handler_method = self.hass.bus.listen.call_args_list[0][0][1] @@ -65,14 +69,16 @@ class TestSplunk(unittest.TestCase): '1.0': 1.0, STATE_ON: 1, STATE_OFF: 0, - 'foo': 'foo'} + 'foo': 'foo', + } + for in_, out in valid.items(): state = mock.MagicMock(state=in_, domain='fake', object_id='entity', attributes={}) - event = mock.MagicMock(data={'new_state': state}, - time_fired=12345) + event = mock.MagicMock(data={'new_state': state}, time_fired=12345) + body = [{ 'domain': 'fake', 'entity_id': 'entity', @@ -80,6 +86,7 @@ class TestSplunk(unittest.TestCase): 'time': '12345', 'value': out, }] + payload = {'host': 'http://host:8088/services/collector/event', 'event': body} self.handler_method(event) From 98364248d4cada5f832a8e735f5e286889c53ade Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 24 Aug 2016 04:01:46 +0200 Subject: [PATCH 149/193] Use voluptuous for graphite (#2929) * Migrate to voluptuous * Update tests * Fix tests and check if Graphite instance is reachable --- homeassistant/components/graphite.py | 44 +++++++++++++++++------ tests/components/test_graphite.py | 52 ++++++++++++++++------------ 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/graphite.py b/homeassistant/components/graphite.py index c262443a94d..4fef17f0927 100644 --- a/homeassistant/components/graphite.py +++ b/homeassistant/components/graphite.py @@ -1,5 +1,5 @@ """ -Component that sends data to aGraphite installation. +Component that sends data to a Graphite installation. For more details about this component, please refer to the documentation at https://home-assistant.io/components/graphite/ @@ -10,26 +10,48 @@ import socket import threading import time -from homeassistant.const import ( - EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED) -from homeassistant.helpers import state +import voluptuous as vol + +from homeassistant.const import ( + CONF_HOST, CONF_PORT, CONF_PREFIX, EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED) +from homeassistant.helpers import state +import homeassistant.helpers.config_validation as cv -DOMAIN = "graphite" _LOGGER = logging.getLogger(__name__) +DEFAULT_HOST = 'localhost' +DEFAULT_PORT = 2003 +DEFAULT_PREFIX = 'ha' +DOMAIN = 'graphite' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_PREFIX, default=DEFAULT_PREFIX): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + def setup(hass, config): """Setup the Graphite feeder.""" - graphite_config = config.get('graphite', {}) - host = graphite_config.get('host', 'localhost') - prefix = graphite_config.get('prefix', 'ha') + conf = config[DOMAIN] + host = conf.get(CONF_HOST) + prefix = conf.get(CONF_PREFIX) + port = conf.get(CONF_PORT) + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: - port = int(graphite_config.get('port', 2003)) - except ValueError: - _LOGGER.error('Invalid port specified') + sock.connect((host, port)) + sock.shutdown(2) + _LOGGER.debug('Connection to Graphite possible') + except socket.error: + _LOGGER.error('Not able to connect to Graphite') return False GraphiteFeeder(hass, host, port, prefix) + return True diff --git a/tests/components/test_graphite.py b/tests/components/test_graphite.py index 9e9ea837dfe..bb60d81a155 100644 --- a/tests/components/test_graphite.py +++ b/tests/components/test_graphite.py @@ -2,15 +2,15 @@ import socket import unittest from unittest import mock +from unittest.mock import patch import homeassistant.core as ha import homeassistant.components.graphite as graphite from homeassistant.const import ( - EVENT_STATE_CHANGED, - EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, + EVENT_STATE_CHANGED, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, STATE_ON, STATE_OFF) - from tests.common import get_test_home_assistant +from homeassistant import bootstrap class TestGraphite(unittest.TestCase): @@ -19,22 +19,22 @@ class TestGraphite(unittest.TestCase): def setup_method(self, method): """Setup things to be run when tests are started.""" self.hass = get_test_home_assistant() - self.hass.config.latitude = 32.87336 - self.hass.config.longitude = 117.22743 self.gf = graphite.GraphiteFeeder(self.hass, 'foo', 123, 'ha') def teardown_method(self, method): """Stop everything that was started.""" self.hass.stop() - @mock.patch('homeassistant.components.graphite.GraphiteFeeder') - def test_minimal_config(self, mock_gf): - """Test setup with minimal configuration.""" - self.assertTrue(graphite.setup(self.hass, {})) - mock_gf.assert_called_once_with(self.hass, 'localhost', 2003, 'ha') + @patch('socket.socket') + def test_setup(self, mock_socket): + """Test setup.""" + assert bootstrap.setup_component(self.hass, 'graphite', + {'graphite': {}}) + mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM) - @mock.patch('homeassistant.components.graphite.GraphiteFeeder') - def test_full_config(self, mock_gf): + @patch('socket.socket') + @patch('homeassistant.components.graphite.GraphiteFeeder') + def test_full_config(self, mock_gf, mock_socket): """Test setup with full configuration.""" config = { 'graphite': { @@ -43,20 +43,25 @@ class TestGraphite(unittest.TestCase): 'prefix': 'me', } } + self.assertTrue(graphite.setup(self.hass, config)) mock_gf.assert_called_once_with(self.hass, 'foo', 123, 'me') + mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM) - @mock.patch('homeassistant.components.graphite.GraphiteFeeder') - def test_config_bad_port(self, mock_gf): + @patch('socket.socket') + @patch('homeassistant.components.graphite.GraphiteFeeder') + def test_config_port(self, mock_gf, mock_socket): """Test setup with invalid port.""" config = { 'graphite': { 'host': 'foo', - 'port': 'wrong', + 'port': 2003, } } - self.assertFalse(graphite.setup(self.hass, config)) - self.assertFalse(mock_gf.called) + + self.assertTrue(graphite.setup(self.hass, config)) + self.assertTrue(mock_gf.called) + mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM) def test_subscribe(self): """Test the subscription.""" @@ -87,7 +92,7 @@ class TestGraphite(unittest.TestCase): self.gf.event_listener('foo') mock_queue.put.assert_called_once_with('foo') - @mock.patch('time.time') + @patch('time.time') def test_report_attributes(self, mock_time): """Test the reporting with attributes.""" mock_time.return_value = 12345 @@ -96,19 +101,21 @@ class TestGraphite(unittest.TestCase): 'baz': True, 'bat': 'NaN', } + expected = [ 'ha.entity.state 0.000000 12345', 'ha.entity.foo 1.000000 12345', 'ha.entity.bar 2.000000 12345', 'ha.entity.baz 1.000000 12345', ] + state = mock.MagicMock(state=0, attributes=attrs) with mock.patch.object(self.gf, '_send_to_graphite') as mock_send: self.gf._report_attributes('entity', state) actual = mock_send.call_args_list[0][0][0].split('\n') self.assertEqual(sorted(expected), sorted(actual)) - @mock.patch('time.time') + @patch('time.time') def test_report_with_string_state(self, mock_time): """Test the reporting with strings.""" mock_time.return_value = 12345 @@ -116,13 +123,14 @@ class TestGraphite(unittest.TestCase): 'ha.entity.foo 1.000000 12345', 'ha.entity.state 1.000000 12345', ] + state = mock.MagicMock(state='above_horizon', attributes={'foo': 1.0}) with mock.patch.object(self.gf, '_send_to_graphite') as mock_send: self.gf._report_attributes('entity', state) actual = mock_send.call_args_list[0][0][0].split('\n') self.assertEqual(sorted(expected), sorted(actual)) - @mock.patch('time.time') + @patch('time.time') def test_report_with_binary_state(self, mock_time): """Test the reporting with binary state.""" mock_time.return_value = 12345 @@ -142,7 +150,7 @@ class TestGraphite(unittest.TestCase): actual = mock_send.call_args_list[0][0][0].split('\n') self.assertEqual(sorted(expected), sorted(actual)) - @mock.patch('time.time') + @patch('time.time') def test_send_to_graphite_errors(self, mock_time): """Test the sending with errors.""" mock_time.return_value = 12345 @@ -153,7 +161,7 @@ class TestGraphite(unittest.TestCase): mock_send.side_effect = socket.gaierror self.gf._report_attributes('entity', state) - @mock.patch('socket.socket') + @patch('socket.socket') def test_send_to_graphite(self, mock_socket): """Test the sending of data.""" self.gf._send_to_graphite('foo') From c5fd665151168aac9dabe0ab8b2c920d3b80445c Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 24 Aug 2016 04:08:20 +0200 Subject: [PATCH 150/193] add ffmpeg noise detection sensor (#2950) --- .coveragerc | 1 + .../components/binary_sensor/ffmpeg.py | 109 ++++++++++++++++++ homeassistant/components/camera/ffmpeg.py | 2 +- requirements_all.txt | 3 +- 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/binary_sensor/ffmpeg.py diff --git a/.coveragerc b/.coveragerc index 8781cf8d4f2..e6b268ed38b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -101,6 +101,7 @@ omit = homeassistant/components/alarm_control_panel/nx584.py homeassistant/components/alarm_control_panel/simplisafe.py homeassistant/components/binary_sensor/arest.py + homeassistant/components/binary_sensor/ffmpeg.py homeassistant/components/binary_sensor/rest.py homeassistant/components/browser.py homeassistant/components/camera/bloomsky.py diff --git a/homeassistant/components/binary_sensor/ffmpeg.py b/homeassistant/components/binary_sensor/ffmpeg.py new file mode 100644 index 00000000000..4a59d2693e0 --- /dev/null +++ b/homeassistant/components/binary_sensor/ffmpeg.py @@ -0,0 +1,109 @@ +""" +Provides a binary sensor which is a collection of ffmpeg tools. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.ffmpeg/ +""" +import logging + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.binary_sensor import (BinarySensorDevice, + PLATFORM_SCHEMA) +from homeassistant.const import EVENT_HOMEASSISTANT_STOP, CONF_NAME + +REQUIREMENTS = ["ha-ffmpeg==0.7"] + +MAP_FFMPEG_BIN = [ + 'noise' +] + +CONF_TOOL = 'tool' +CONF_INPUT = 'input' +CONF_FFMPEG_BIN = 'ffmpeg_bin' +CONF_EXTRA_ARGUMENTS = 'extra_arguments' +CONF_OUTPUT = 'output' +CONF_PEAK = 'peak' +CONF_DURATION = 'duration' +CONF_RESET = 'reset' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_TOOL): vol.In(MAP_FFMPEG_BIN), + vol.Required(CONF_INPUT): cv.string, + vol.Optional(CONF_NAME, default="FFmpeg"): cv.string, + vol.Optional(CONF_FFMPEG_BIN, default="ffmpeg"): cv.string, + vol.Optional(CONF_EXTRA_ARGUMENTS): cv.string, + vol.Optional(CONF_OUTPUT): cv.string, + vol.Optional(CONF_PEAK, default=-30): vol.Coerce(int), + vol.Optional(CONF_DURATION, default=1): + vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_RESET, default=2): + vol.All(vol.Coerce(int), vol.Range(min=1)), +}) + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Create the binary sensor.""" + if config.get(CONF_TOOL) == "noise": + entity = FFmpegNoise(config) + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, entity.shutdown_ffmpeg) + add_entities([entity]) + + +class FFmpegNoise(BinarySensorDevice): + """A binary sensor which use ffmpeg for noise detection.""" + + def __init__(self, config): + """Constructor for binary sensor noise detection.""" + from haffmpeg import SensorNoise + + self._state = False + self._name = config.get(CONF_NAME) + self._ffmpeg = SensorNoise(config.get(CONF_FFMPEG_BIN), self._callback) + + # init config + self._ffmpeg.set_options( + time_duration=config.get(CONF_DURATION), + time_reset=config.get(CONF_RESET), + peak=config.get(CONF_PEAK), + ) + + # run + self._ffmpeg.open_sensor( + input_source=config.get(CONF_INPUT), + output_dest=config.get(CONF_OUTPUT), + extra_cmd=config.get(CONF_EXTRA_ARGUMENTS), + ) + + def _callback(self, state): + """HA-FFmpeg callback for noise detection.""" + self._state = state + self.update_ha_state() + + def shutdown_ffmpeg(self, event): + """For STOP event to shutdown ffmpeg.""" + self._ffmpeg.close() + + @property + def is_on(self): + """True if the binary sensor is on.""" + return self._state + + @property + def sensor_class(self): + """Return the class of this sensor, from SENSOR_CLASSES.""" + return "sound" + + @property + def should_poll(self): + """Return True if entity has to be polled for state.""" + return False + + @property + def name(self): + """Return the name of the entity.""" + return self._name diff --git a/homeassistant/components/camera/ffmpeg.py b/homeassistant/components/camera/ffmpeg.py index 6803ebb49a3..d5055e942e7 100644 --- a/homeassistant/components/camera/ffmpeg.py +++ b/homeassistant/components/camera/ffmpeg.py @@ -14,7 +14,7 @@ from homeassistant.components.camera.mjpeg import extract_image_from_mjpeg import homeassistant.helpers.config_validation as cv from homeassistant.const import CONF_NAME, CONF_PLATFORM -REQUIREMENTS = ["ha-ffmpeg==0.4"] +REQUIREMENTS = ["ha-ffmpeg==0.7"] CONF_INPUT = 'input' CONF_FFMPEG_BIN = 'ffmpeg_bin' diff --git a/requirements_all.txt b/requirements_all.txt index ccc638561e0..af472e31cca 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -102,8 +102,9 @@ googlemaps==2.4.4 # homeassistant.components.sensor.gpsd gps3==0.33.2 +# homeassistant.components.binary_sensor.ffmpeg # homeassistant.components.camera.ffmpeg -ha-ffmpeg==0.4 +ha-ffmpeg==0.7 # homeassistant.components.mqtt.server hbmqtt==0.7.1 From 0c91ba4a50e58734553bfb00fad5a3abab8abe43 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Tue, 23 Aug 2016 22:09:43 -0400 Subject: [PATCH 151/193] improve gpmdp (#2951) --- .../components/media_player/gpmdp.py | 97 ++++++++++++------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py index f6f649f3b63..85f697cb1e7 100644 --- a/homeassistant/components/media_player/gpmdp.py +++ b/homeassistant/components/media_player/gpmdp.py @@ -33,8 +33,9 @@ def request_configuration(hass, config, url, add_devices_callback): return from websocket import create_connection websocket = create_connection((url), timeout=1) - websocket.send('{"namespace": "connect", "method": "connect",' - '"arguments": ["Home Assistant"]}') + websocket.send(json.dumps({'namespace': 'connect', + 'method': 'connect', + 'arguments': ['Home Assistant']})) # pylint: disable=unused-argument def gpmdp_configuration_callback(callback_data): @@ -49,14 +50,14 @@ def request_configuration(hass, config, url, add_devices_callback): continue if msg['payload'] != "CODE_REQUIRED": continue - websocket.send('{"namespace": "connect",' - '"method": "connect",' - '"arguments": ["Home Assistant",' - ' "' + callback_data.get('pin') + '"]}') + pin = callback_data.get('pin') + websocket.send(json.dumps({'namespace': 'connect', + 'method': 'connect', + 'arguments': ['Home Assistant', pin]})) tmpmsg = json.loads(websocket.recv()) if tmpmsg['channel'] == 'time': _LOGGER.error('Error setting up GPMDP. Please pause' - 'the desktop player and try again.') + ' the desktop player and try again.') break code = tmpmsg['payload'] if code == 'CODE_REQUIRED': @@ -65,11 +66,11 @@ def request_configuration(hass, config, url, add_devices_callback): add_devices_callback) _save_config(hass.config.path(GPMDP_CONFIG_FILE), {"CODE": code}) - websocket.send('{"namespace": "connect",' - '"method": "connect",' - '"arguments": ["Home Assistant",' - ' "' + code + '"]}') + websocket.send(json.dumps({'namespace': 'connect', + 'method': 'connect', + 'arguments': ['Home Assistant', code]})) websocket.close() + break _CONFIGURING['gpmdp'] = configurator.request_config( hass, "GPM Desktop Player", gpmdp_configuration_callback, @@ -159,6 +160,9 @@ class GPMDP(MediaPlayerDevice): self._title = None self._artist = None self._albumart = None + self._seek_position = None + self._duration = None + self._request_id = 0 self.update() def get_ws(self): @@ -176,33 +180,46 @@ class GPMDP(MediaPlayerDevice): self._ws = None return self._ws + def send_msg_with_req_id(self, method): + """Send ws messages to GPMDP and verify request id in response.""" + from websocket import _exceptions + try: + websocket = self.get_ws() + if websocket is None: + self._status = STATE_OFF + return + else: + self._request_id += 1 + websocket.send(json.dumps({'namespace': 'playback', + 'method': method, + 'requestID': self._request_id})) + while True: + msg = json.loads(websocket.recv()) + if 'requestID' in msg: + if msg['requestID'] == self._request_id: + return msg + except (_exceptions.WebSocketTimeoutException, + _exceptions.WebSocketProtocolException, + _exceptions.WebSocketPayloadException): + return + def update(self): """Get the latest details from the player.""" - websocket = self.get_ws() - if websocket is None: - self._status = STATE_OFF + playstate = self.send_msg_with_req_id('isPlaying') + if playstate is None: return - else: - receiving = True - while receiving: - from websocket import _exceptions - try: - msg = json.loads(websocket.recv()) - if msg['channel'] == 'lyrics': - receiving = False # end of now playing data - elif msg['channel'] == 'playState': - if msg['payload'] is True: - self._status = STATE_PLAYING - else: - self._status = STATE_PAUSED - elif msg['channel'] == 'track': - self._title = (msg['payload']['title']) - self._artist = (msg['payload']['artist']) - self._albumart = (msg['payload']['albumArt']) - except (_exceptions.WebSocketTimeoutException, - _exceptions.WebSocketProtocolException, - _exceptions.WebSocketPayloadException): - return + self._status = STATE_PLAYING if playstate['value'] else STATE_PAUSED + time_data = self.send_msg_with_req_id('getCurrentTime') + if time_data is None: + return + self._seek_position = int(time_data['value'] / 1000) + track_data = self.send_msg_with_req_id('getCurrentTrack') + if track_data is None: + return + self._title = track_data['value']['title'] + self._artist = track_data['value']['artist'] + self._albumart = track_data['value']['albumArt'] + self._duration = int(track_data['value']['duration'] / 1000) @property def media_content_type(self): @@ -229,6 +246,16 @@ class GPMDP(MediaPlayerDevice): """Image url of current playing media.""" return self._albumart + @property + def media_seek_position(self): + """Time in seconds of current seek positon.""" + return self._seek_position + + @property + def media_duration(self): + """Time in seconds of current song duration.""" + return self._duration + @property def name(self): """Return the name of the device.""" From 63e3d202604f338389a14669c02b304145ef3bf4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 23 Aug 2016 19:36:35 -0700 Subject: [PATCH 152/193] update frontend --- homeassistant/components/frontend/version.py | 6 +++--- .../components/frontend/www_static/core.js | 4 ++-- .../components/frontend/www_static/core.js.gz | Bin 32126 -> 32126 bytes .../frontend/www_static/frontend.html | 4 ++-- .../frontend/www_static/frontend.html.gz | Bin 123277 -> 124422 bytes .../www_static/home-assistant-polymer | 2 +- .../www_static/panels/ha-panel-map.html | 6 +++--- .../www_static/panels/ha-panel-map.html.gz | Bin 43920 -> 43913 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2278 -> 2274 bytes 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 841c2c495f2..78bd44c1c96 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,8 +1,8 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "7901b14f238956024a19139d6c479d68", - "frontend.html": "850075be728fcdb83328cf2cb50a9f03", + "core.js": "1222f00ae060652376f7ff0b48470e43", + "frontend.html": "fa112bdd88ccf8aef7548c8f56b4ac82", "mdi.html": "710b84acc99b32514f52291aba9cd8e8", "panels/ha-panel-dev-event.html": "3cc881ae8026c0fba5aa67d334a3ab2b", "panels/ha-panel-dev-info.html": "34e2df1af32e60fffcafe7e008a92169", @@ -12,5 +12,5 @@ FINGERPRINTS = { "panels/ha-panel-history.html": "efe1bcdd7733b09e55f4f965d171c295", "panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab", "panels/ha-panel-logbook.html": "66108d82763359a218c9695f0553de40", - "panels/ha-panel-map.html": "af7d04aff7dd5479c5a0016bc8d4dd7d" + "panels/ha-panel-map.html": "49ab2d6f180f8bdea7cffaa66b8a5d3e" } diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index e336deae556..ce03134e0b7 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&&"object"==typeof t&&"default"in t?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 je({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ne.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 Ue({authToken:n,host:r})}function u(){return Pe.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 Ke.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?$e({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||$e;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 A(t,e){var n=e.message;return t.set(t.size,n)}function D(){return Dn.getInitialState()}function C(t,e){t.dispatch(wn.NOTIFICATION_CREATED,{message:e})}function z(t){t.registerStores({notifications:Dn})}function R(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 L(t,e){return!!t&&("group"===t.domain?"on"===t.state||"off"===t.state:R(t.domain,e))}function M(t,e){return[er(t),function(t){return!!t&&t.services.has(e)}]}function j(t){return[bn.byId(t),tr,L]}function N(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 k(t,e){var n=e.component;return t.push(n)}function U(t,e){var n=e.components;return pr(n)}function P(){return _r.getInitialState()}function H(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 vr({latitude:n,longitude:r,location_name:i,temperature_unit:o,time_zone:u,serverVersion:a})}function x(){return yr.getInitialState()}function V(t,e){t.dispatch(hr.SERVER_CONFIG_LOADED,e)}function q(t){fn(t,"GET","config").then(function(e){return V(t,e)})}function F(t,e){t.dispatch(hr.COMPONENT_LOADED,{component:e})}function G(t){return[["serverComponent"],function(e){return e.contains(t)}]}function K(t){t.registerStores({serverComponent:_r,serverConfig:yr})}function Y(t,e){var n=e.pane;return n}function B(){return Dr.getInitialState()}function J(t,e){var n=e.panels;return zr(n)}function W(){return Rr.getInitialState()}function X(t,e){var n=e.show;return!!n}function Q(){return Mr.getInitialState()}function Z(t,e){t.dispatch(Tr.SHOW_SIDEBAR,{show:e})}function $(t,e){t.dispatch(Tr.NAVIGATE,{pane:e})}function tt(t,e){t.dispatch(Tr.PANELS_LOADED,{panels:e})}function et(t,e){var n=e.entityId;return n}function nt(){return qr.getInitialState()}function rt(t,e){t.dispatch(xr.SELECT_ENTITY,{entityId:e})}function it(t){t.dispatch(xr.SELECT_ENTITY,{entityId:null})}function ot(t){return!t||(new Date).getTime()-t>6e4}function ut(t,e){var n=e.date;return n.toISOString()}function at(){return Yr.getInitialState()}function st(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,Jr({})):t.withMutations(function(t){r.forEach(function(e){return t.setIn([n,e[0].entity_id],Jr(e.map(dn.fromJSON)))})})}function ct(){return Wr.getInitialState()}function ft(t,e){var n=e.stateHistory;return t.withMutations(function(t){n.forEach(function(e){return t.set(e[0].entity_id,$r(e.map(dn.fromJSON)))})})}function ht(){return ti.getInitialState()}function lt(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(ri,r)})}function pt(){return ii.getInitialState()}function _t(t,e){t.dispatch(Gr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function dt(t,e){void 0===e&&(e=null),t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),fn(t,"GET",n).then(function(e){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})},function(){return t.dispatch(Gr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})})}function vt(t,e){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_START,{date:e}),fn(t,"GET","history/period/"+e).then(function(n){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})},function(){return t.dispatch(Gr.ENTITY_HISTORY_FETCH_ERROR,{})})}function yt(t){var e=t.evaluate(ai);return vt(t,e)}function St(t){t.registerStores({currentEntityHistoryDate:Yr,entityHistory:Wr,isLoadingEntityHistory:Qr,recentEntityHistory:ti,recentEntityHistoryUpdated:ii})}function gt(t){t.registerStores({moreInfoEntityId:qr})}function mt(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;oru}function ae(t){t.registerStores({currentLogbookDate:Fo,isLoadingLogbookEntries:Ko,logbookEntries:Qo,logbookEntriesUpdated:tu})}function se(t){return t.set("active",!0)}function ce(t){return t.set("active",!1)}function fe(){return du.getInitialState()}function he(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",fn(t,"POST","notify.html5",{subscription:e,browser:n}).then(function(){return t.dispatch(lu.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),Mn.createNotification(t,n),!1})}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){return fn(t,"DELETE","notify.html5",{subscription:e}).then(function(){return e.unsubscribe()}).then(function(){return t.dispatch(lu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})}).then(function(){return!0})}).catch(function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Mn.createNotification(t,n),!1})}function pe(t){t.registerStores({pushNotifications:du})}function _e(t,e){return fn(t,"POST","template",{template:e})}function de(t){return t.set("isListening",!0)}function ve(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 ye(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 Se(){return Ru.getInitialState()}function ge(){return Ru.getInitialState()}function me(){return Ru.getInitialState()}function Ee(t){return Lu[t.hassId]}function Ie(t){var e=Ee(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Du.VOICE_TRANSMITTING,{finalTranscript:n}),ir.callService(t,"conversation","process",{text:n}).then(function(){t.dispatch(Du.VOICE_DONE)},function(){t.dispatch(Du.VOICE_ERROR)})}}function be(t){var e=Ee(t);e&&(e.recognition.stop(),Lu[t.hassId]=!1)}function Oe(t){Ie(t),be(t)}function we(t){var e=Oe.bind(null,t);e();var n=new webkitSpeechRecognition;Lu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Du.VOICE_START)},n.onerror=function(){return t.dispatch(Du.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ee(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:L(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 L(t){return(null===t||void 0===t?P():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function M(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 M([]))}function H(t){var e=Array.isArray(t)?new M(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 M(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=Mt(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=Mt(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=Mt(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=Mt(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=Lt(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=Mt(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=Mt(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=Mt(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 M(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=Mt(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=Mt(t);return r.size=new M(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 Lt(t){ return y(t)?p:S(t)?_:d}function Mt(t){return Object.create((y(t)?z:S(t)?R:L).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 Le(t){return null===t||void 0===t?ke():Me(t)&&!m(t)?t:ke().withMutations(function(e){var n=d(t);at(n.size),n.forEach(function(t){return e.add(t)})})}function Me(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 Me(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 Ln=0,Mn="__immutablehash__";"function"==typeof Symbol&&(Mn=Symbol(Mn));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,L),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(Le,J),Le.of=function(){return this(arguments)},Le.fromKeys=function(t){return this(p(t).keySeq())},Le.prototype.toString=function(){return this.__toString("Set {","}")},Le.prototype.has=function(t){return this._map.has(t)},Le.prototype.add=function(t){return je(this,this._map.set(t,!0))},Le.prototype.remove=function(t){return je(this,this._map.remove(t))},Le.prototype.clear=function(){return je(this,this._map.clear())},Le.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 L({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),L=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}])})}),Ce=t(De),ze=e(function(t){var e=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};t.exports=e}),Re=t(ze),Le=Re({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Me=Ce.Store,je=Ce.toImmutable,Ne=new Me({getInitialState:function(){return je({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)}}),ke=Ce.Store,Ue=Ce.toImmutable,Pe=new ke({getInitialState:function(){return Ue({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),He=Ce.Store,xe=new He({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),Ve=Re({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),qe="object"==typeof window&&"EventSource"in window,Fe=Ce.Store,Ge=Ce.toImmutable,Ke=new Fe({getInitialState:function(){return Ge({isSupported:qe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ve.STREAM_START,s),this.on(Ve.STREAM_STOP,c),this.on(Ve.STREAM_ERROR,f),this.on(Ve.LOG_OUT,h)}}),Ye=Re({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Be=Ce.Store,Je=new Be({getInitialState:function(){return!0},initialize:function(){this.on(Ye.API_FETCH_ALL_START,function(){return!0}),this.on(Ye.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(Ye.API_FETCH_ALL_FAIL,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),We=Ce.Store,Xe=new We({getInitialState:function(){return!1},initialize:function(){this.on(Ye.SYNC_SCHEDULED,function(){return!0}),this.on(Ye.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),Qe=Re({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}),Ze=Ce.Store,$e=Ce.toImmutable,tn=new Ze({getInitialState:function(){return $e({})},initialize:function(){var t=this;this.on(Qe.API_FETCH_SUCCESS,l),this.on(Qe.API_SAVE_SUCCESS,l),this.on(Qe.API_DELETE_SUCCESS,p),this.on(Qe.LOG_OUT,function(){return t.getInitialState()})}}),en=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),c=1;c1?" 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 L({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),L=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}])})}),Ce=t(De),ze=e(function(t){var e=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};t.exports=e}),Re=t(ze),Le=Re({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),Me=Ce.Store,je=Ce.toImmutable,Ne=new Me({getInitialState:function(){return je({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)}}),ke=Ce.Store,Ue=Ce.toImmutable,Pe=new ke({getInitialState:function(){return Ue({authToken:null,host:""})},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,o),this.on(Le.LOG_OUT,u)}}),He=Ce.Store,xe=new He({getInitialState:function(){return!0},initialize:function(){this.on(Le.VALID_AUTH_TOKEN,a)}}),Ve=Re({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),qe="object"==typeof window&&"EventSource"in window,Fe=Ce.Store,Ge=Ce.toImmutable,Ke=new Fe({getInitialState:function(){return Ge({isSupported:qe,isStreaming:!1,useStreaming:!0,hasError:!1})},initialize:function(){this.on(Ve.STREAM_START,s),this.on(Ve.STREAM_STOP,c),this.on(Ve.STREAM_ERROR,f),this.on(Ve.LOG_OUT,h)}}),Ye=Re({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),Be=Ce.Store,Je=new Be({getInitialState:function(){return!0},initialize:function(){this.on(Ye.API_FETCH_ALL_START,function(){return!0}),this.on(Ye.API_FETCH_ALL_SUCCESS,function(){return!1}),this.on(Ye.API_FETCH_ALL_FAIL,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),We=Ce.Store,Xe=new We({getInitialState:function(){return!1},initialize:function(){this.on(Ye.SYNC_SCHEDULED,function(){return!0}),this.on(Ye.SYNC_SCHEDULE_CANCELLED,function(){return!1}),this.on(Ye.LOG_OUT,function(){return!1})}}),Qe=Re({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}),Ze=Ce.Store,$e=Ce.toImmutable,tn=new Ze({getInitialState:function(){return $e({})},initialize:function(){var t=this;this.on(Qe.API_FETCH_SUCCESS,l),this.on(Qe.API_SAVE_SUCCESS,l),this.on(Qe.API_DELETE_SUCCESS,p),this.on(Qe.LOG_OUT,function(){return t.getInitialState()})}}),en=e(function(t){function e(t){if(null===t||void 0===t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}function n(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},n=0;n<10;n++)e["_"+String.fromCharCode(n)]=n;var r=Object.getOwnPropertyNames(e).map(function(t){return e[t]});if("0123456789"!==r.join(""))return!1;var i={};return"abcdefghijklmnopqrst".split("").forEach(function(t){i[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},i)).join("")}catch(t){return!1}}var r=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;t.exports=n()?Object.assign:function(t,n){for(var o,u,a=arguments,s=e(t),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 M0|23+Ngcrf0Av|xO8@`> delta 12898 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 MKh2#2P9VVn0Ju>oe*gdg diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index ff7a7bc71bd..ca3462f16ef 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -1,5 +1,5 @@

uaL7?& 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 delta 170763 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