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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 CZ;FKg delta 30475 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 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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∋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 Z(*KyAeGiRTq|X26pZs87xY<;81^|c7Na_Fp delta 11500 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

WuCip_)-^Hcnl%JLAG5 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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;nD8ufB9B z$GVpbIcD8q-O2q)@vG!-BW=Tl)3iKqrXTtFUN&fw?#)TXu8g-;PTZY&GkxC7^cM+t z53P7R>r%P21Q`YDkOe=mgOa$LO5wyX59`-Gat*=9YH@)+&zf5?G=k02_&NW+1(Auh^x^vr= zKt7r4DYKS)MJJkM$i^Jmalv%!`vbQ>PyH0I^|{zOwF1_CvkQ{DnzS@HPV*E-E%i#> z`7}mjoyp~si=x9`uuCv|>ujF#q%yBdX3H6gjjW}b-dio+F8{J_UIF77t5q`T69k{n z3FIqMSQ0SlqR+cKPZV};Q9D1w^oYO#>&&eTQ`5aNl>B#RF5Icb>$AnrH|oi$RX$t_ z=eW`wG&h(PPtYuVzB0j0MAA@Gq~b!1f#23i*KSS`?X!KlGFaBf#f|HnQD@mD9pOV9 z%QUAmEly*dU~R8+`m)pWCM{=ECiY7fi)X&*k9hJ^_(17~n9#l2i#n!+EonVd!8T1e zPJ{1~pqoqBikjzMUS6*A-PKnfxv}G9tD#QmCB>?noyv;N>ZhJg<9PZZDR`pyWG$zR zWxk26TX){AJi)PihMTU=W3#Js0^PV2m!wVeeAm_6F1O&)oY}h$mT)kvD{?xpbmfGu z^r#Oyi$x?h`J8-GY`x)h=0lBVcY-ulq;zeLS#ENk>+Hl?>}BQbGdR5F8qPeq1i%TpxPjG`upm`wlK_;snS`j3EDS3bpv>0Omz z4rKCnW)zht&Qr=Pqp zO`W{1IO9~2+C~vm@yKb`XBJOdnc$8N@|GbsvPirpb<|-EXiMKBHY1UlvfbU^? zi1ay$G@qLD*P=H(t=eh&jNx|I0?U&tP0l3drfM#1@O6lGxP9OFo7}V4UZ&C6Gvuc$ z&kSBW)qCZcIhRCshbAr*m@}(3d+EyB>UUQ{>x~_Q{xt4CdFuSdz6C)->$qDun1d`0 zQaG4tct-jqYXEE`tDtg_tl+|Be`QRjsf z-a4nHGxWaJNcTQ!61@`S%-y%;;HNVzhXYj9Cj>72wl=oe>}yeI^_zWfmuOjE>9~}C z%0c)||EZ+A&zz(jCuB)Zo8z3YMAw8@Pw$ZMb>6 z`ii7g;Zvsf&r?~uGW>%Q$D$o`s@DXHY%O2q*ez@FHu~yJ*O!6u=j!9jPoMtW9TEAv zU+8a1Y4PV<(La*Q^ur6qYu_F{dA@4zuMhutUtKL(oS@;q`Q{mQ?W?*rQU15MeivIT zyjUS~&)#l!Y2cg5>;8$BUO#{MMRbnTfoGbjF z;TEl3dwG2?HD#T7lv7sz+em`lmM8szZ|=jxzpt+^>*U=1LT3i+@q0fsy3RW8Nd3)s z{!?M&$~6M18~8tH#(D^FdT4$4oF|yuRO_~^{XpqOS+&c%H5aa(UQl9nV_xnIzDIQ_ zk$dGPW%6(O`P``Wnpwx0GV|Lp7d0}&JuV7N?DFe3x^237!Tj`?$c4|7xp%X;_dR>| zFLZnLR~~EeEf%k9l*BI@h|c};b*J9nb620qIaeQ;-jypygc*R^KV*?@!-{Wld`ol7NzH~o;jyYRo~ zTUPnm-T8qgvTqXa{=ITOBfl!B@`#Cst=UAbspW@f z18!+4Ufz(i8*~Dum>J*v5@{~CIxZotKSle^R%N@?oaD1-0=BU!r`hn?oa6aCPoX{C z#Z#hRzVz>h;1AUj`)b7UTKb-7Ar0hUo2l&S=Ygu z6>ekjVV)^-tpDfIt$E_^r=+^Cty=e-{oAL9WhWS#cEq1`cU$IK`?vV+)OB|r$S+Em z8hf?-RdDFz@7of#&eT8dd@Fui@B0&n`Edu`$)TX>ZupwZ9ZM+b7lk zymj}>;|Hc;fwi(Szx$6Em>tRLI_cy!Y32XhdDCY8+Ps-Vy3xt=i$>>O=QW}wk~?m# wiPkwg@zz%LsXXToWpr7WC4LF{W3l6&ZuK8EnN7X>FaKw{TCqZEp&$bT06G)ljQ{`u literal 1832 zcmb2|=HL(wTp!NFT%1}|mYJLyU!Gr-om!-qRm`w7JU9RL3BiBbTo;Q^v@QDH`y`J? zF{8L$DdQ4%k@yqmSH@}O>8f!WL8_U*dsP1Kbw0I8_qNwM4T1KS9W`msW=>C+nET!0 zb^E#^=MtfF(&iz##;*&1Sngrj?(~1(>faKR&&%>Xk2OC0MmX+k;Ur$|oJV)LtJ$w@ zsQh!VGQ8e*pIqJ6gQsumTU^jDdBe2p<}zn-4<-RaISajA$C4TE}aODgN_cL zre_*7iKnG6b5ZUsPgUHL+^2X~GGEjwvSHI18MDjD<$;!SqG#`pnf_p*0axS)FAElj z_uUPw2YOX?=Uiefw#?$%65>?EeT;oRx9pMaI=luCVnlts10@cf>~_*z-tzR4#;2%^ z6!S8dz-PCnbu~Yp*5UlPX|q$W;;T)6*b14~nSagbVl+OsI%c+$*bCLkQYy0!umrcZ z6{Vk&ICpi%@q`_U_m^l-Emq=J6R1AgIAMj;a{;gOA}qUp#7sT*^nir^n#*yO@xSJ_ zHhKDGZaKyMvRIo{+($cg#f_GUj`_MhETQjiY?Zw@Wx5^v^PLkSs?@hGe3i2F;wdkM zSDWwu7QDWIVU^Os+Rl9~Lf&e;#rG_}%z7yIPOo977~94YGxIxH8cXz>1>6Lc8>UU& zuGzrgw)uc8zn#Px--+4Bb~1RmpG)MgeY<++)MGd9co!Kz*>+)C1xE{I~GQQuVw*2?wbz9$FklR07@ALlcThF&C3QU=PC_p=E zW!EB}DeeY4g_sy@wy&9Rzqu+_H~g?^Smx)1t$Z;NC9||8C7chgo$M5F?8^5I_ZF-_ zcl~+-<4%{O-eELT3jr+{i?WaFW?aDSOFq#r_X6IIcqP#AKY0ne3 zy029!FTbdD-Ry5+L-)tDbG<*B|84T!tRi!?H}O)|q7IowRe~l5c5KbiSik2C|D%*I z@_Wy(xLf>sp~`BDw$^FZ-jyY-3;*3*ydvtb(C=jSx%Sb*rUh=fm92MY#>Q1M2XUUY zy*hnbh}o5StwK+_Ch~Ce6^OqTTAO`+_O^vDZ=ZjirO>-#R<3k}+h;+WuemFGf_uEy zE||vc()01wrx#yL=9)Z+-*C+JO8mLd2#=d<<;Mrp*Ob3y zo9`YtDeQDx)fAVvx+N_Z3D@^G9$dSs?aR|2+dn7PmetH^`feYVlAf`9b$IV_d$H|B zQ~6Fl51f-=`0DEK^7WqU{kCzrecBSCqj3AchAa--*V(hqf1IQ4?*8%Z`SW7Vlbp=9 z?4R(??6k$tS-bc$-}rX@_TO`B^E9VhIl8;r#nR7SoVdH$<&pQnBfg)WdcWBux3GA1 zdiU(x;uix=E`8vUzFt-H|J~Kou}O~+}L*V=3KkZpj*3t#ovxC{3tcC+I%n_ z)~vs>tC%irx%s?vPshKHm)Bo3xwR|zpOKXH>TB_nJ?0h_7#-dIK7iwX(4r?P5qHiX z+Sap-@s`dCU5_c-tZ$y2{P4vJN!GNF4%;3DT3>Qbh&I`-aC4T!or{52E}YvS!<}O9 zHmPOtV)kJBe-eMij_c1m620(0)9hELEred_U!Sj*K0Wt4r}d<&to|qK>ldy~=x^~9 z&u{D6Z65NDud~^3$&())Hz!B@&MH}-}ZbvyMI34X2YsExwVVVzrIkm`9-_ktlrPbW;?&sd^>#J|NBmbtzOG#?Or>1 UrNe$T_5ZAUc2_4Zz>% 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 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 literal 0 HcmV?d00001 From 2237189c864b7c5523ccff573827654801b4267d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen 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),c=1;cA5UP)*-m(WiR)lC67% zkNf4SXTE;A*w=f)Q8zZxNnVd`{CZ!W_Ceu5yUy~vzwhk6CEBeb*L*O+K%eK@@nXX> zk6kMMe=K1HEf9~DLP@P_1q#@Au^K6fLa+Ud`#~F5K zqYXt~K7an~r_u@WWs2{f_RL;ZQE__znMo$+n{FR%dMcN`XYIWoN6#&saj zmDaPKPu~25SzM=ex#y&(wpTyNea}04-NE3G*b<#{_gpVmh&P1ohsI{%}UuIXaJ&V1!@6pf3j?Wge<~<8MXS+J#4O52sO2^Z;=RdCb zRK*v%(CwMzlW2{+ber!{W?OW(-TV4Ao7H5`>lNi??z(C<(mzr{m(0DQbT%(5?!m(X zO*y6Q=cmMfe(gQ)ox|&0=7Cer&Dm(a`1pgTCjONrx)&D(GPFd0uM$fA-67+&z;@ch z_?KIv?`MAB=Xbo`eR z3+Bab;F%?}{N&fumme?Qy*vHdsRIvHbM~V9Yf9DRSS&wGVuCkaZ zKKC>Ce)VYKw-qg~6CXw&o^Q$<-?y`Y{e{`jBm6Dp>n0uu%J^_7E4v}Uvm;M@msxC^51ntr`}PCce#@wZeR zw|O)Cm-8$XvHKlT`84=`NNKv&-}4RJvXKIZFAFVrx`v}X>=io`Z`wt5zZ1vh>k|!@ zTfhJIHR6i|M^eu9rf)G|L-q2}o2c!r|<{{{coh@Dwf$$f3L)|%^I zp9JWf7t|}=nRjMY-i#mHcklkae0kNYO2e;{G#~k$xU}f0zxMV&HP0Vx*mhIHo5l1u z+m6IJ54Bu(a#^HaJbRYw?unCi3V)WbHv2RE!2YO(;=XMBG6%lC^8LS5@y%&o%ctRm z(>{MO@n?|Z|8?fm+{iuByy`X;C*RioSa9R%`Sa0b2gTMn?3@_0Vbz1}`{wEEb*1U; z-#ByYpLg%VZ}q&r*0+}F=p<8FlP%|e99@+0c=Oe^2lKCg3s`qz?Zo+_#X+~06?Fbm zF+QSb!pHPRM*F?G$^^L%Lk}KK4`GdxylwmX(>{J*>w9stRd8@hC-aH?B_d7t>#J*j zD4kDN|MOU;?b7V+lO^4kO<6F5#fi0p`PFT1x!#IbTkCFDZQLx%+pb`~JtD^AScH|} zWfiH`X<06_YxMo|^D1w2rESi%QDJ=g+rF{GL7eNk#?Lt)a@d@>uh;SjPh{5G9uS=M zvvx{lz?p`^Gl91jZA$;+{f_iinZMipmh)>( zk$@KyIHIZEdR- z@8~+N@$RRE+OH=bE3H*uu3jUz@CMueWAPI|i(mc5^@0D0(ZjOvZTW`H+86Dt?5r#5 zHta4gE2uHKVSDqw{DhH?_X}o_+~a!z{I+)Mw{CTpQ?5L7%&8FwzAvu zH8Vke!Td&!WREVoKk3U%;iVsT?+!DPi`Hjih!<@=w&q&=?X~mwyNd;% z-)d%7Bp&u|!#sOkw=(5h)6LnHb6zb?Xb)SdeA3$C*!HV=F6Rxtm~8(j=%4=4^vsX2 zE7Ez*8%%0$y*!?%7O!5MaIYty_wRx3&X)#-<vTqBi*Lb)_T{^y=d*iy*n2LUMhIZyj&x&x#+Ru zA)m_!=O|A7{AF&AT}O`Ehous~Q(oS1yS-gDdwh_3 zeaSfcafFq={_3;7ybI-bxBT0e@#XU+xB6n~vuY=wHysy0TBm#KcI2&l@>4bUusy0Q z{8Lv@wPE}JoaZffljPr>sSOW*neqJYLH!NxwuEXa9WUWo zKJ8|;Y|5)!z8dwvlwI~E#$E1M@XM{fS4jwcb`x;{0LU7c%|RX&=zW#ayZ zty7km@3I%#H??)m`ZI}dlDjs^&w4p+#=_f=RqnF8F6dhw;G80q{AW+`!n6v3e!UI3 z6P_=cX|BUlvt#eBvheH;=cn_P#YpAcm6*=!e8-ySyewn&wo?ph*BIjTWDk^_WJtJ{ z#oAVXdPmTfE}xX+T?+HcmR^`vy?@!4yGH#{%zu(!GO%B5{i&3Dy4AFzu%N1}=F{(l zeDlb@tu-IWqGf zEXZxCJ0)v=`_j$Ag5}ST$<=c9-d8U3`XRvo%1ha)?3heVN9c!*R!VuF4q4?(%2woD zo9Q$)RqXU@)yWTSd>dW9b$W^H*iqK3udwg7e)IDe={7!#1PdycSA5_Klaikn%^7!X zU!AoxOK+3C%*5xb824oVXm*=YyLV=7!K&Ej+SN4yu~Vf2II82k`_{5@yX|&(_wHKn z<>epPGLQQRl~tYGcCW1J*eQ9dR>Y{0XBi`S6&-d;A=G*>; z`kj{Sm5YCJ`Z_F^(5V>D#=Ku36k3c7c1`HJ$cS`p{wU)+8$kd{8#J)%a)sr=^QV%r@qz{ zQxHz!_$jx#w(qFM&zunJ1$%0meocR`b9uccL*jmmp4(z(f8;#o&yn(%j?PK{d|Jof z_RHLJ%M^H-7y=A^5}R9&UH<%zHOFweOM=+_iA=`Lme!q#e#>h-VkeyxT;`C!G)weE z?Z;xjeOzTCn~i^7-WGSYlW7A3>q^NL>x92mU&~mZH0ONm?DsM~fA+awzSp;&<-&2n z|C8PqaxTzensUys@yVR&0SEbmHvPD9I_7BNTkh!n> zNwvdaGiis_eT;%ij;sHsHGYfA6*qlwb<$k!)csujmlc^V?l{7H&trG(zLqt+8&i!| zcX3EHoX+^c=n~>KQP6g_c3TXyXs_Gv`3WVnR_&R#Y?~N!&efoK`8yr=-4fBwoGF&- zzbj8V^OCcA25;ew_ot1S?~7cy)cU{Rz|3YA9*>PY*H4?zHDB?Non13{)xYOc78X7< zk^6XBgSSjZ^6`aEA?+DnS=N{1f)%yAelKOo)@6$oc)RF)Zb1K@#h0@FOZ>Lme7eG{ z|L^5V-`+S`=*G0|1oCmS}qY_{T#;l2My<;@Dd zJG@VlPS$*LKdYYV`~BwZSMGf#4D<6YZ8Kq7wB_Wt;U}#&PR>v2-}qUa>6nqO{?gsZBf$TfCjE z|NhM=FWB`vss8=jhyUc>Jg;R^S+H{Znmeh=fjeI%lt0fX|3Bf@kIQR+FG^%Rdb7BP zmr<5sx$X~+>Y6r(`F!d%Ci9yT{&y?y-WPcIyuIOvrWPiA3% z6r*JQqHPc6vwvC2&+^Pg_TrS?sec+)1hg}Ws`i+?`K}i%SNkHc{}`Xm3?ad-Op7eO zUQ*J@I$Tq5E1<>Z!jFSt{|x4>75=;}!@YXZlgU~c#%uMjS^ZzT<(y%WTjCGa{$)Q? z$`7^6e|dDgb?TYRibc&Tk3T%xZj`UH=8N_PyBKxH+lE6U;k2j&bDOnTp*Vzdj@^T9vTUP4SqwZb1C1xBsKq_ujJMO3XNGkR`-x>*66Tz2%V3 z|J^n3^)qLm*6@zL@nM6CLPd#l5x+_PS%>QHAAXe7^Ydn#Hmh>CzB&8pm4L2rqYXp$ z@qCd>i>Bz1pzN;KE{($?^xb-Gf%lgvKs{K><- z{pX46g7SxW8O^?4ER}q`>$T_Y#tDokpH(y6pS{oseLr^B@O zYa7oA#9CWc1%6JLZd?wyf&*dq?1qViH-Pu_H@iq#V1FK z%7xyGJ-Po=^lWD0hUqybcf8HaXQnb$=7(K3oI5L{{(*T$*s5D|gK{&4p1)+3^foCH z%X4Mv$_Z|ooDj1)OJO7A`kDf2TtCV4dfl zDHA>#7RIEvrq2+M-5+&p>w~k(m+xNvc`m1a|uYr<1oYrDGA{qMCR zqiX-Zc=IITe+jEPw~wC26#1}k>rBdniq@}q8Fg^;r5h=0vs2H77xn$06_J;>@5+q= zjX(##soOmtItRZ0e%0ZgO3tf&m7#TuW7YMAr5~NKtx?GN(Kqq0x$FGr6ojEg(ZJrY*^kGFt)Slndn3MDve(7$llzslR zIXPA1#8%JwUJJH($vyPUw5d0Ka#!ty_1Ou{J~tS4RsYJ(Dr`DfBdI=PZA{UIqLUMS z%@$YA?S3Y#za>(u&$`}t-TQZ0CswBGK0dkU@4Fuf<@E(+n~F<*{d&N&G^H#$tF14x zL5^?HpXD5a+dvpk2=071tx2{^h45T{>Z7iXKi<@e5Y@$=2HHfv;O+B ziU%$A|7oz(NkrW#tIKZl#Ftv{mTwaLGyU$4hcCm!elNchxV_pcDtN+#?=$1;IzC^P ze17<(=f&#tFTY)D(iT`_r0d8%<+#wj=(ViERc!tze$HBW-fc_b(FJ(|da0M#s)I`7 z0`@L5c&{2U{p%5pCttj)8lByLE5t~2i5$JTTSUZ2?6G}kp@Mve;QveB+rAd3SvQ>Z z{=#(pX0eN>{av27-z7Fo63^(GUi-H5l@Ld=ga_x%*@>rK6%=f$|Mg9v?9r>1qf>vb zGU;MD-E!%1j`;6Sci+Y`dFPn#+}C$RL*mRw4WoUAtBMTf>8B`svU_1rtmt|pFgw=! zY|!nOr|lhMJ6C5Gadu3t&+<;Gv3mE|{@~jt*$)>ieHe@P#c{~Ka9%&>^Rv?Q{l9nG zt&m+dPyPzWAECZp-k;lLWBY%7T3%kq_?P8s-LE~hCes_w-B`9^zSupx^%GO(1TQ*T z`FY9|uPZA`jxheaCh(oB^|W30xkrMnY>OL(x7utzm>8NebHUdYmvqvO=3nr9v~5jW z_N|%-jsLq#9lltpWY>1Ios(Rr`mT}X;oRH8L0oO+=N>$Nd$1vWy|BsUub&@Wo3ow& z)6qq7ypPs|UNNkiV59P?w0GsP>Xx$OB8yKv|L{dQiYqw(-Q%6H@7d?`KGghtQ)1q{ zA303*yJF}2e#}3fZv5l7|9svB7kFl@n#!)Q$M)fZld72lk@=EqCo61>myL;U=4q_D zd7(}=ef^KKvo+?kOy2gBH-BlBw9oBd>Zd19Uw&{$Z~cSvi!%F+{40Ll|CMCBG4WKQ zvU)-M@%SV`9vzDhGnT1UyxUVQE<8(qN+;8{t2#3uMY8^6&UnJ*lJ-^P-l61#z%Nan zznea5i9J42``OZ~^>>>Y({s@eBFVQRb_h&c={+|g^82T)65Evwmn?np`=^Sp-DN=? z8$lQM^Lwx5skls9|1c?{`&wJ@4Wa8wKklzNJZ-kv!UeIrzdmgC43*?sYj`VCtAM9! zwou}7^#tc2>4_KIk2rp@6BpmRCHBStg?|gmx8F;>wb^X?{Y1m<9Bd{%6E1H4YuQ`; zHMjFF<62t{AAK$L_j4w9Gl`j;uvEx@%K6EmN7?hG?6Ig1N10lL`=*7)=p?Q=ckgmh z&x7;HJ1yovc(mp?&nsIw*(gV6<3Ft53>(*Ga9xUfQF>#~U#nR^<>p>)eOMa7V#3Gt z>%{b}J64H$JDUINN?OMxC+sul{vn6vu#Y>BKAB^Ah|{g7{)}u%KEl^%Y3hOdV)tjNQi6-T<$&LYDL`J?F+KsY+1$i!YyFlxi#vm+YfUe(=3ozFVT-YIme0R%p#7fT9fbGjMKB5RdQB%<87O{$}tOP*Ble- z>9J^$SM*{o?0Y_Khq$2GhplsW z9F+-Ru`54$*-6c0(LXiy*~Qtx3oiS3d%Ir@>~D8kU%Kz^OJ$eY8S)!1?Ue`)IPUrS z(3&|6aqewXW}Prhsk;4e+5wLVhps;qd*JW^^uW=US?F@RXz`ONuL+^(Tawp!F?P~CL zUc73?oT$)kn^)Ls?%%iXanGA#O~J5I{gat4=Q=BL3vXzi`@Zhv1eIIGcNSk%i;)#O z%D8UAXXe7f^6B&AnV2#g!+x7|PrZG7X{^W9P1_$#*>lp;JobdL8pE9^MSTb1$zOPL z{!giIIbP29BR)KXaaGfkbMBk$Ov@i{n>qPEgYQoBPe-MfPo6yWV947~i&WpV=!ow6 zukUxc{hHm62g_FK&Uc%5S^K%n)_X6M?=U!gU95g|*J5i=1P78FnZ&TcwdiMl_ zecPR^iQ!Q;S_}(fnT}qwk}!C1{jP=Gl&nkBPTdioVx(lVzo3sdT;f1_J7WZU>-i52 z-)5TZ-uvyGe$Dq88zOD}j5Hng>&*Y1TJ&>`ecg(m6>IF}uGXyCn41tdhySRq2D{k$ z>mA?rpIKlef6}*3m+{%sg1u_DW1Gd!+i%$FFP?o$`|yS<>@j?+JT_drwPi+2?T#A? zj}~t_@mJNNgEg)9?%v|vho>-Jol-AlUN3C0TKVzfqfFm&f(oABo10_Wy!7yeZ+^^9 zR|GsIj|+=esidg}7R5|I>zFq?zuhx`-PMyCJ?CBRZ_Z*bF1pps(ALg%sjlSSPL5{^ znhdWa-e-x~-hY!7nYGX0(29xo?r||CKG}Ivziub{wJ3|VcQk*;X-@RabIx_RT{G)T z;(Q*yfcI~nn=oYPv@T_{DVJJn-bXAQp8_FfV#p-7}lLCG+k{ z3z|(&Qer#(_@}UU)YOw^9S>)O-)-{^?)-85@vYoBuh*|~50+}?aL%)}6`0kU*6q6d zHLJ&;$2POlHr!byzw_sgb*C%+w)Ne=b7$7yc+JhxtB>YIXNY`hwx4tM-F2^DD$@@a z-Fe{Q17_DhnAUyHh2OeO zKYp(M`iJfL=?Z_(P3?AQ+_d#*z}p?)*5!+9$WGLcs`~XMvwZRGpU?UK*WCI0^5Wy& z@^ZGX?5e&z`DnjedS|uOy$K(x!sl(#@|K(xT=Gu+j!>dr?$yj`US(faud|x4*!o3e zl~U05YXa8gpXSVu2v+@^V0(KOLJht4` zYU$e+sHM9y`Q_!4^Ih%4dU(+KJ5Fg-mEGhZi# z@`5krvfPq;CT(<3o844tA;@yCFM!eY=t1qgWmC8geVMyoO#EB<@6W%&E7u6N?wx5A zAeZv{*sD&t)?MFE-+Gc5#C9_0+Ly}W&jA~fLUUvuCGau2+gS_#>od5fTRDaQ)r@6j z3t#BnN`CS#l0!Vp*wX8WSfs}09Rg~bwrV`h&X~@2Z*mQrr_!l_B`0p_P6}dR_nmg@ zI+L-Z2xDSwnsmd*Na>o7+pj46bYj|<#{AFV%QVTJ)T67k-i}u=ZUKD zrV9%h8nbyrHzsHfX7f*+5mpF7td*$y#G4-1|?!H>R(l?gdU$p2AgW2p2-&{g;+Aja> z2>xY!>}+yv;#4)>xd${HPX|o+;4hQyDy{J}LU)hM-c@XYr}|g4vm1%eyB+JEw=2N2 zadlG7O68cnv>`{I6~gIgyw7hjrbaZj=RNKpHROV4&*z3lokpi4>9_||lvnz@@Y8>g}ynAKG$ zqY*tnfzxA`rRnCBNpIcW&wn!GZ1)1U^Iuf#57>9k`*P#u_Pk4TFGjq$dwdF;_i`&f z;p|n(mY1y_&h-@a6F#-5pl|cK;v&cOg2oBw3tuUJ3A&_Nbi2vAKxy9GOp&%=j&vti zS#ymUu72I~isYw+?^n6B@^s%c6E|KDvBsHdGD?NTS0Qe{mzl3Z zBIDWmbRTQ-F$<+0Q{wvd(^`USWp2ehPp7a6-nDKogkDeBddjmQN4R~r-^T?Ly46pM z1w~eTw9?zt+xxZDIbvf}<;P~R4Oz>#)cxj^{oOfTHz}q<%X;mURb1UZ%tgY}Jf}tL zB-SjQ9?0UwVI>>r~ONF7SuA^JJ0R>ou~($n-2&_ zJ&@eMu=7BBV%tm8V;`1l=O$ITB%7tQYE?08So$}yL0OvFKw|BoM@4drn;h;ty??7w zts8r}Y||R4noAolf18tZ(6*aLC`E7Xtvx4a$6C2ga#BCW{BG(e&YKJiHJgquZ0B45 zPc>^k$0F`z-2%=}Z+0-rq$#XDyOAqeGvo8~9hyOX=eE?_rJrsHOqUU|lUh{3LuI&`IJFT%s_1j%E-I4Ko$>Nif^5+v1EmuUhmQmm-MDeWK>sAuLwibN+F8?~ADu4O1k0_RXJk zi}^^yqfEEmVGOTR_ny|X-LEqvPJeo=oRXSAc1-5AjYdFn+{PH3*SpxwX5nVR!@uW58Z;H=Pw_ZiwM3(FX9|P1%{4GebCy`Q z_s~=6^w!g{?w9@bIn{%9&3y2@=TccT6JOrje~&(^wB6lrpnrtbb|H&VSda3$v^|q= z@p_77cDTp2b0%1?{}JG2=su-RZ%*K{^)@24U*@pK@9BE1!oR?GlGH5zWm?v1k(o7n z9bZnVJG!ZfKlXR?qFSG|ZfhKNDKKo1PT)3j%Se8FMf*r|#X`TolYg7(ZrNGKv}uX3 zMv+%shX20nf?^WO=QTVMeQGH#ckH2B(RP2wVCl2%PapI4&AfK%XxOx(uH5Wk9fPSN z-m5&>_D?)$eSK4^)qdNxGu7thCIwylc{g_3S;lUYr&kW8UFV;WzIZC*Hv5Q^3-4^6 z7|rv|X;Ut|jV#hI0`e{G237p22Z| zs9Y%L*m&~wy_i7h1&lv#sIR}!Z?fGjm+A1F>S9gp%SV+WB|orAz6)GE^I_#C*NqFO z%=n#}xldMdw?O#Zt(v9%U7l{QMXX1o-tiq z?9O)YC9E48OZ=`ce^95u>Zo9I%d^Xzo5$Zj=4-vA#2Oc;>pwCxH#D`W?b|*3|8?d0 zpIS4dl1`m#S@J)=zhN$Sn|Fh<{B--RCp~XXa*=>AJk?W^+Mc<0VGzs4{OAVf@_#-$mXpma#a;(9e%tlX zPWO4~g}qyi9$zjxkgV)<(N-@s^~-zFB^C0A&vS26lyVnNdZA^_d})h~3S*ZkhxnS8 zNsCvC-a7MCrr1YL;Mm!W$<5Ih3QZzhukYC>(I=aKZT4ybwUaBhY<7=hy?lrBVfMrD zl;5%Df*es?zibL>w)M52f70f{KflCmvClRei+6uSqpQm|PCK6-the~yDNU)ZyaDmO zEFNXf;h&3oe){PBax~CNkH2CbWwBh-X4RL_!mbAww)=%!Xo|)18wXC*z4LwVukZ8n zs~NhLQkJRv$85-!f2ffq=3eY|Qu?jPbN|Zy(ob&h*?*PSDlf<}_q4sXlc*>Et=;u; zT@kJU{uAcs`#$E+YOA`Tw2pEAG0VSZ`}MsfCv&mtr^uc8nyoqW@$O|JTyA;}g8RiE z3QaEwD3)&6ynRKBX5~wAsFDfp_QZY5t#1?BbeU z$d~QEd+|ln`K^oQ)!IxfkkW1oJ9t6Sz=r_Mj!EFIK||) zon6*U;>?2g4f=CfqE)q9Pcz<&cqhEoC-9~Fiv*h$|FX|;R2`bJ+Fc;`Dx)5ZWX^Nj*ZpEjc$tXcw0*J+xANy*|>+Hr*w-} zKVxgL*ur1RmemWls(E$YV+n1to47VzYeF%@`w!Ls&pRF8dV;^~s$SZwW4k$4)?a@A z)3T(Z@ZpbTSGVu8TQt>xwNOI%Op9G^<%U9!wvHYDdDc7i)h2O0-4kM9RU8|6kU3HL z8XxO&2ZQO%XPEsToXma5m{cHgKCq|jrlrW93?G+Jz6mw+9&0jwzk7VooatR@3e%() zMmj0f{+#CVVPfC*O~s{sO-IE~^)pJ_&Xi$Di8VLaKhLgK>rZdz0qN^03r#%Ep4K^X z(Cu$A@3ChAPDO$hmo9vW`PQ}Swb_)@7kil`PUy?9e;3!ediUPE`v>hiT-4jA$tdvf z3(KEeQ?N2WwsFC)#w3YX#~Z8?aPkY!gM{}>&ZA>;Z#h8%>q)zH5_Gx_zBh;`I`dH?x+9*YtnBS$*T*#eK}Xd|&G3 zzIMEKKJ>4H&Z*2ZYii>ksJ_;g{2{Scsn|axpyqIEp2W?&vE_I5wjWY`n|b2*I>7@4 z8ecYD|83bB+IirJ_>XB-tN8@IJK2(DvYv^kZ@w_QcGtvvV%J!8R(LU)AAjqq5Rf;! z>u~g255re;wRGEdath`*uzqpn-qR=;u>4(k(%OgvcFZh)9Mjfh{1h#(yffda`H9;Z zgFg+u&JEcs_RgDCx1e3|i$U0%7}bp|)8r~Pif9zi6wyw8+!m6X{WEMv@S0zb<#*ZJ zRem}zKYxSGm%6G?m(Sb(|M27FdFh?|Uph9rOFt7mHud?JPaF4td~tHIyuAI(e+*mA zHZGih<^H?=HNRiXFI!U`;*=w_ETeM!m$Xg69Jja43RQRZeXAz>n8EId`Nd~3J7%Ux zS9bpN`X?lwcR0h^jqS0!NZLEq6A3IecVGQtw0-jYVp^eyTA}fNOEuQw6KyhE87A&s z|Mb$F3`UV?hNV&F$9ff($|kH+y5P9&LnO~{1_z`2K0GQLXNR6U)%SF_`PUGBfeE6b z!P}?)`KTo0@xCcUQRX$ri*0c&-{Uub$xKgHzAM-Luc2Bt;mL-HUaC@U#!u&I{`g_Xym?atx~bvtJdqwTLMkNE1=`czLr0L_wfIEYrDeNzRWAnl_tLo^-s+J^bOnB2Q9`l#5fd1iP~Yi<+L} zl)38SI(L~~b(!x?skS~^JyGn~-3d!RhW2Pr_1klHkz$;eTq}D_no865N)i9w7ip_m zg9G+0^Q&rTRGl_qvERw~bxL1W1+*xYE-K^RvA0ci$$crYfL^7mq6SkuI)7;Xb2{MQ z*Qs+>bD_G>-{)U0Uz($&p1WY-;roHbzhtlJtUJWF#;H2A=F)8y)t!f4i1bVq=;QCc zaU^*2((bo?`%kGh-=6!=bgSO>DSTcs*Mm$%XKN)dzO$e@Y4Z%t$2rR%dRN=~c3ivv z#mDxj%b-bQ@bGa#t_SI5KtPc0TO|C(7P^da0OO>2DonqJPaO zCnBdwLNa;&ma-Mmy)hwMkF9vmdpP*y^BWhg@Tlixq+C0bC+s*O>XD2w=gU=PW@UHm z+s|oi+g1CwY1_U7uQ-{x?;Pp*#_9SZ>fOAZX%{Z+ycHWTb82r|@EPBi>rdJu!xvuMc}7d7>ycBm zIqQPC9{=w(>`dAy5@e=1IY;unx0zwb(hqT8o-?ky_H!A>B;Q@Bx|1ePUFh-ZL*t9g z8KNfww5YvnS0Il4VxiWZYWtM!@lZ%-W?NS^Y#f;tu;d2+huE zYxtI!-}LW=?}9xn|4)9HZ}}&<#5Po>wyoZHzj?KnXyT%2<*&cF|B#V*X3Uj-`?6i2 zS6kD)H!ruWpS8&AAVZdig4 zifZSz1uvK&y^pR#v_Bz9+E0 zyOB3-LBXLXXa8hq&pDX!V7{VKh0gmOxp}lYFFR1*uN`c!O{nrO0DfiGR|VT zz6lHgYzzgbUI_Bt?CBC%n4{Qxz~1|9=FPApXQVilXZyC#OuX{&!i>Ae(zqqoZew*3 z`C*!-Y+dNPIJfcSZ2i``KSEY^Gr7*;Sd#bPLeQcLE&Y8RQ+WRi*EGi3HHoj5lwEY_ z#fL2?SVhGqnZ->BP42fS2yqm7XYIJ}s;XDZ$*pH@P5)!Ze@wFIX|i6d_>T|si(+MN zFVGY}wRQHgc75~G_***R2ODMaH{c+xqV+oesBr!*l=mhD@P1OFC!CM6ss7KdU;mRpZ?2`~CkE z7cc(hQ1N+H?ulD7yA?Du|1D1Wn)t>g#k4BuV(0tSmkoX~?9<&I_~{5!r@Cs3m;6s%ak+MKUfqXCw+~SV*}m)T6^^Oeo%Qme zbG6-|Sn>PPHA(vy z^t8FVJ{2f!QPoS_voUmC(J3RdtDBc( zEf{S5;#u;^XRo#e#<+cP`(9+@roCLWReO5Ks{-}a&Cm1n0;JMUuDv!&r4`BS7rD-CDA==IBSw0?-f67%(CLs{ksp9-HH;X+&tE{(sg3? zCRNT#&GW1C_XjOrakeAb)mKq$?g#CuYn_W31&pgTE_^ZwJoxbS3(be6i3ek(C4RsD zrBEaA{rY|7nz0WuFP9DT`g{5BzGm^W(QH%K`Fxd%edL3nB7f7|~2r~keut$v+fw)FqikO|-F4?lan zMf|izz;7q3y!32+#g|LFRYIrvd}UeaGd=71;|)c3n6#LzS@UEIJU6m0-MfV8PIbEd zR{yQhnzPOuuIB!etmm>}yGq;6iT0&Gqq&*${N}JiHWz=vhv=l zZA>?f-*F(uRN%1YZpOB-U5-;%UQk?D#rc@a=y>?jW}%&$#?NPLSjg8s*XHV?^WK4P zHPcRcnLj^JsIgw;ZP~xrRJX$NTH*uKfLZe0Sgf{X4aO?T=XVTe3Q5SWku%SE2mc*o3&nj&iiD( z;J<^rt@ujRZux)lSl0T%t!|QK)#2c(TPHWANHkCT(AggT<(Y--#H31I|4njVE?(QZ zVDUH2^M?f|KH@m`!T!Iogv_40zu$76-+cJ*!GoOtEpt7b<1&4#eOHLOCZ!+ZNQght+YOXx<`t|EKF%;c!ExM7b{&<$rZnNo0 zyY+PbBqy)lt*z+6x`ChPj&4Tr+igdqy2DmlTTk@jy}!I{1y6_RH&5PT74Eg0T~}`C zP?@&PMA$R1bK>$(x1s_(p@{hPksCA&Fbcu zT!9#)!|D;Qm(;cS&yln%oTVpJYHn8dNnGuhjM}e7p|8F&zIbC663aR_*6F#T(z6Y6 zhV6VweBMju>o5Ojark}y!|5q~2Kh$>7CIkR@$ay#TW7H0^56K*%C9;>2k+c{BK9$E zv+(@A+ZGfCrCQwPdn8lJYVuuV<@xi^e~HcNZqT2z?42#2D!=o~*RdrfzELW+)8u9t zsNLs2r5;yx?)S$qAr*0+&BYcoXG~Ulr@FFziP2P6iCzD%xVR+k>#06(xbCQbaIuYM znnJ?2%WEr&g%?+895s6I!~fgW^!jy8$-gi4XzfcCJNkK!K<@VEDS=wC35&B5CA}B8 zHP5_!g!#FbS=PCY3#Xh9^H_a$?Uq{>(*@JmguOpyUO%*>L`*bgC2wTwvT3r(v)fsF zC5vv|sgatUIq$H^`KM2!9z1N7DDstkILm64bKc#PHtcnkp)a&QZy9T`-A}x0*5y|Bt(z|x%o1&%u;i$OOC^tHkK-)HYxdRa zI7{yDHrbgv%}+&tlBiTSKi`h?Pm`8zZuz9s8M9oz;GW$d^=E4fOm~ax&tQFe=g5K^ z3*usJPjV)IaXiggyffka+_zU|zMU7>^Z8MX-L{s0W%@<876&vw>T%Ld`Mg?g$DlKKea6kz9_w!ZLR52(Z4P$C}qP2zKq6473(4`9Lv=lK31xl&bxn8`_E^e zf0do}aVzIa+Rc=e+;>^;?lMX%Z_n-IYLkjcE1%Et5W7L%UGumAElFYoHoYLn0@)wL_71k*MbtXTCbC~jw!^Q${C@1EJnc-S+) zVzyl#IW<>8m_w)4k#WIfE|Hm~hHH0mb5|A2`k_AIm5%wR5@ns2MiDNYVm;{#IzL24 zF)j7HwUPhj_f;9&cI@Dd*l+hCcJ8Z4mU$eN|6Tab^RIDf-56?-CgGvWdx5lsU-W?Yn{0tcD-5i!foN-BFD+5XXLe3n?hCW6p(T1{)c#q|JY-6IHmh zHTrx05f#sv?eQ;@LNuf6KI!&Y7t&PImU|ZbXery~Wo-AOZx?Mn*BHUn zW+PeE5dUWL!fDgj-C4xLx8|`ot3+_%I#pRIK8@ankcBh4xFj~!MC|(=7Qe1pFE97B z@$&SmelNe3&x_aC7IwLgv;0Q$f-{yc4u@at&*D@GdXyl)r1^~3<@G_bCmuOQz3Mo} zd?jGkV`eoc&N~IdQ@^;T-AZLuJ^7%dcIru|b^-w^sQC-bWK#r+O$slT#$2r-+SOn@DAPs>v`(-3T73j zKNJ7J{$s6q{!89{_~K%Ai=m{;b(`RZA}wxPO41i z-`FUmSW>laq7X;PCRLl3tqJk(=6?ywkym|ik;|dH`u689wU07Ro-s@p_+__7B(=@B`q6pxA}U0AaIb3(O|gg?s+ zzV_97+@`c=WH@sjX;JLISD-w3U;oErZf};Yahf&Z=4!?~4fX=&y`qN`6(qkbH_-fL z_JwiTwONX%4>yW_xa8=WQ5~jc{-$KZMnlt(FBiY~c{VJo_|?z5f>C1^U#h%f&#FJi zj;-HmZu|b<`y~-Yp8`W0KHV+)*{EqXLD6pOlb@VzW-s`gAO24}_(3n({EJLs{wcK_ z1{P7Cr};moispa)(=Xz>>PYGQH&2Sq#Y%&|E%txI_U!-Nc;)k2nOUc%ED;yyJ60F8 z%ueLl{lC^P{ez}0bMUl%T+s1y(T6RfK5uuly=jC(S_t9VW&a1FW*mQ4|wi5HnU56%~TD$DGoR{W7FY)j0irk5( z%w`&%+rjtWzijKmM=IO4PoK2zrgD>B=k`DK3DUnK8hO8&eEU;Zbjgg@KSEPOu($U0 z#_C3y2S5L+Ec(Rss^xWO+_m?HU)wJ4acVbzqb`-cZ2cK?6{g^cp508(dN~@(R(Wi@ z&~(*Mw*8=Y>A7=^$GGF4F5IBWf5PJ1)%1`_GJ!tcPvl?6>2U`emT)UsFMF*iWV2Ml zXUeMtCC5g&%n5N8dL=xSe}k?+-_6dfv@^?CLM?tSTT9U7+#Ho$>$n9hF`Zh|*mgX< zW;2oT_w+e$f4>pm&1iC=Nx^XBYtw{8n*>!D)T;V{ubPIUsLMX zvJ4|H-j{#!v)tEhaZnHBn6b0z>bt1@uLDmB&gA~~{m$&gRpve}a^05k5%<6JZ#(lW z>wciapEunJ?+y5V|33ak`ETu!d8ePt&L|(ZLv^nOa9jzmcFNYFUPWy zSu1DFeQ7b1lQG5e?!u}0(d<43bLaG&(YnOh`N2#2G1q3HH%wZ;UHU9dx>U~S@$^o6 z<=%kP`dEmFq4ak(RYh@OApnZTo5M7 zvAnThTd1t--K!t1n2+sTA?eII?~;a=bB58<_vW)Nt^T_IAj_Wnd#+52T=9K+^orNF ze{w$%6?6--$rtb;j4zJoQd`0b#&(Go~r>^DlrRr@rbnToHz5n?6TL&2= z*R9vuqyOgOr_A;lXU@B<%A ze-7K3cF&^!$JMW%do=eR5Nf^sp!ci7ev!8S=I4~R#zcI*f5Sf~>h6-%zLj0+A*po_ z|GxWX#((DD%O~HoX3Jfga7I>(H|*Dzon8~2eeO!NL{@v;T(*H_?#BGQtp)Q|SzmlM zW5V&1{j3VfZ1#2vG(1zuKZ|>h++mq&Hv6X9)@6sENIYI3aLCtTLBgj&&Z$7TAaYf(6%%+|WJ^JBv zzUbkr6Ft<~o)qmg$UFWd#@#qG&_r49lIW@n0%sCjQd!c14o#Tg{qH@OoI^oKnN!-= zy#1dvpGR%Wh_Bxy!%xs-SL+1jG+DKZzHEC_L3Efb3t<4YR z+xUI0%p(zB&emo7wp$e+h>2gaEMk{+n#bAg+fv#>OgKfSm#;c~e1fyZ+%p#cFK}pl zTe$b}kLbA@HMVYuS$)Mb{?x-TKHrzNmo7P&pB9~ATQni<^!D9|ZO!wJJ9Vcn zJim6gOjF7>A%^sp#|3fbOQd>4OT|Llfa^d|?SWv{QrF8Rya`(1lI z%Qpe>-`@_*+sn?SKJ{=7>-7zNM=YLM7f+fvL4NU$MgH|mzA0XgnCrH6&!Xy@qt5!@ z4^EkICO{%!)t~k67!srA$dyj2U;0W#bu*9VJK4k48a@}6$-MI_d{Fz<GPzs<;(58r+(!3p8ApRJ@w=LSyKy{euPhn=d-MSx%qJDQ*n)sPs;Ob zvXZ9Asd2gGFWB>R_N$ugMeTb6+UJB#lgn_744%KfILmc$VC-7^t&0+}(o5Fl?+tF; z7kPVy*`i7JpG|d}6;ZpDbE)A}=^5NB!j(Nk*DSf_XfL23SFkW7&*|<&-O?PpwOELy(n@cC!cE2aMa&;4?CJBxL* zyZoa~2hA;gQeIfDTc~#O&4>3NW?v~ktQ~wsp!eT4k>0qKS44XMZ4>IP`yuWtzf?>v z>*0i5^|f)Q9vzYL?oECC;o&siH;0${sXHh1&V2mAKJ}RfkK`)Bng1n?-R|cfp3sow zwZNuE_i2xP)~0_N=Z};tZE3&y+b=)m3y8xaLwNv8yZsin|INv+xs&Pl&VbI zK5Z}O^Y^VXJOVTB`t~os^~r@@TUBgd!B3Znip52?3S##PZBl={lYUsE=gL#RIke$t zUh2V9CuL)&r@Xkk_oMRbFrK#RZ^5&5=J=ia+|8x`a(d3aio>%tzQzh}JhSoVE>)l2 z%+H}WEADD9TAY)4c$Y&%8c*=*)$<>^tDab?^I9+C=H3j=Jk#msv;J?N%3Gyp$05OZ z&u!S>eBK{DL-E&s^RH)i9sle7_*BTQuBxdLEu4p6n#^Oi6$_Me@71_tu)j3s zQrjtxQ@#lw(>7E{uF1c3@7~AuxlLvZm&Ng({dHD);swhC+20nI-`{rhAFslPDvp2K zWG~Kp{p{?;GcQ(2FaF}bY$0!%zHjDy@8G@X59&Y8H_!L}S5~2)>iSmQJU@fKCi#8i zukP3R*Yh*Yx9)v=PJFrP-$R;#U#}j%9>l`9XQd1KjPj)~8ve7}-PxS#+}Wl(d!I?( z&7I$SlE3w(Yv;MHQ{1d-Ts=R23)A1?wOccvKEIc<^>*&xw(g6|!k4_LyY+Uvfo4Tu zo+6pTk*mrbn$k8>Dpd-s$aYp8a{>9p*EK@2Kx5rM#ef zi`_NnAG^$A!L;sJ`uCZMbAK#8)U!%y_vcNF)28!m=*e%dj89E^-|$WR#hN$2)-h>2 z?vPMu3c7qd_J7l*_3er7pDpv0{qHq%b_m}VoxL&O z*v_?ioE@1{p0b-Z+%Q?dpvw46^8YiFPNR$~Gn@p|_O#wwxb};DVS?@JBb}f05|h@* zwS5nttnzJ=@1AN?z9j9~N1NH-MM)jG!e*$~sPS*2mBPLGj)rE6nk>muOLQuuS{5cw z+i9u!oNv#c$2POBou2h>DWh4*rzY87E6qiH?)&FIY_D7XLL6MfdjY>CZRmS$?0h;OPFE16}J)65FD3vz~tS z|9G19)R|7-_m-l5uY0zAvBl^!DB=5xtQT|L@>p7M04=>^JXz zytsei;m3>j{R_Oj((ljRhCZL0{I)Nd7FIK4ckK)PoPJ-&<7jH%iQmh9ZIj8^cq&Bf zqqQkR>?gH`9?@la5_cwFS+>K`F|JXu>({LI)mL-ezT8-}`&ZENvfpN^&hqB(wkMrw zTsSXARq60vU8%YiFB9@x4HHsIe6N1gI=o!hG-KBT1{2OZ!ra240lTHAEmAP6oFHz! zW-{|7(+b9!XDVK8|L>FZaO(}JmmF(-Z@9E~O1Pa{@UDE(+f}I>^KU=>$|hrSa{4;+ z!(Q7|-@kR5z1`-Ln8~g8Ju4ID`#gCeqxEp*u6-|#?Wn#cK36@oOxiN1^w<`ULu=mG zB_$nP!o0Dr%_PrlXYogdW7iJ%$xUINu(svIkGYQoWiN-^IVVCP>+B94 zW1M$fXYYn%8gA_h&R4!h9G|szhE}@Fg-Ks>uWo;MMqJymf9IkXR#rE{HOs97);q^7 zy>)c$rpo=S-AWl7rx_jE5|yLs^da9>{<+nI*@|*MmItT2E@8N9!WWzrE6l{T{mk#K z$m`(>cePdSX3x&OKCyqUgxD$O^Yi#CTdP)G;hVhbcm&_~+jUotS6^L0JF#JgQTSG&8-rz@H-)%cY846A?cp}W{t zOZkWC#h+Q%HR(^$k$GX)R6i}fWp$}dJN82TjNs50MQa`x?qWV3>1lmXE2PkO;myx7 z(_=Q6eDRd29I-y}c-k4+Q=*-fDz84ysHnUj`9o_~)2H5* zcl%b^XFrgdKc^-n=)tI)lTF$rB_?K5S;x^;k8T9q@-YrEIuvwSqrO)D z`p%M_eAiCyjBtC)zO3!m6P-P#C#r;%Ut5;9Tub0_Sbx^&Z(Q8+b^cXFH?K5uyt6&& zzEh?8^*oKc>=%taIoIr2ed3Ge^i`);%zD7smC$we=F3hWuG)l7&{;gDf&Y4)e@t4&130$ zQ`mOp=K?#?8O!`Xy9IZYc&=Y0_Ae~*47XYAA)nVz#3J0~a?i!TVk?{`&coSda`w|q z(PAdnuo-_wr}w2v<#hA z$1Jr`%T0KO`Kq1YCs$ORzgH7`clN?Z(G!nfR;@W?5_fCK?1IR9D?$qb~GjE^lg8S-Z?kU$ERV@x<3Wqeo{S_3U|kV>9#d zkF$I~9oG*@xnsk-eA?oodGq>HuCV_(%G_^Ghw_fu~A?B8sQcgC zTf_H1;qT&C57gN(@0QBTSf!$h*{z?IG;Or+vINz$p0G*P)hyhubvjSK6x z*gKcMn|%G!bbd|QMBZmPZzmORG<&ppiu3!LBiEkI@N*M)5iHX6>=svf%jmd%?nBvq z^PkSRW_SFu<`xqc&0^iC(+!_o_8lwq$u@kUmi^e0;pFuR-wcfeawV?qZJe^{&YgKq z+n4Qmey`_l-|~++omK{CO}9?0VLcRlA>;b`>)Q>LPgg!)G~xWJ+&k<4Ims^lbBL|X zCND*M*PEc#CqkGC{f)V3wljX)MjgXd*NY5}vw6F*Dhq2IK2&+=5qGV3OT1OO z=E91nFHZ3)%5J@@%s6Es!_w_sth3Bh{)Zg?Fkgc=UF?77rO*D8{=2mOf8i4~@pQuz zt;_kcd?DTnORIZ!?!U=3;T-GEh{k#BFL)zvvfP~-^4H;VaQJ%GM^E|Vcxz*Lo(KiW zsArtG{U$@p$0VCrG`h>&|otn|1ZdBoFQA@Dug< zcPG~!k941>C{SMBpVD@!G_Ff!`GuCZe)~P{WfbX%ip{++(cx2<=r-@^dzUl5jXYp% z`#LJ;n}>1e%uSh-fA3pbea~6=+?-oJ$J7L0AF7-YUD$7@mA|TDMV9B}i)(am?cA}= z`c;Bk;mYrKW3Q@g+Bnf(_l>g64)@1P8XVjo<^syw(ys@jLuLAx>{fa_Sqa$DK! z@;ZMaCw)w{urAa66p(ysvHzYdbIapN;-(^xFQ?u;w$QcM|NA{7s}<*NXFaod{Y__G zz$?yDnQ8z29G01%AZ1h7AJlebDFbh#t9ZJ-wZ6)w!OZ2 zR>Fm0^OW5gJ8d;r>DQQT;JbSNL~nY4Z8iVw!z)y5%-CEN?Dt;(x#)bOZup9|+E*E_ z1Zv9Nn%2U2VEvg}?w)qm8{3`o`QEy{IQxET)OoF~aaLP9xYIH#R?DUyobphj>}H

>6$8mzS?C=KMcvP3c9aIR7Ipz7xa5F75yI^4+>+iFY}sZn&kvhr53|fu@7!HmE`G39)U;z4k7MLa4XLdntgn-Ph4k;$GN{;J=*Tt0 zs=C(p_%n-pW|ph0LsPeXtg1|wWmDTGFS+p1yLV-YbKQ?kS>1G~plk6XnakEHzm|EI zL?-Ips+{p+j-X)2|BK)Dh`)4M8#yDP?2SyY{?QNp+scGq9L`kA>TeYDaFR>qXqA{I zUvmBz(+pLPUFh3W`f|2S1^{eNqyZ5x}O#J_CQq~vU|rIj+i z*=bSh<_CF5_7H;2NB&@-pWKj9Z<`A=tx#@!|Pmad=^)4_y^;2}; zt{ve4VIM^DZ$5o~bm^r9mnt^yT=Yz4@9MNs!RO-YTW25`iu3% zv<+oTRG1gZ3H-O%H*5Cu^O=y5dro|Un`C>@mqg9;oL*19b*?ma=(jPw8nk?w zfMxc@TLMqs=jfg~!Lt0@vi8gUUU$4> zB)M`6o3)0-c8)f&1+&(%WMt;ov1JVx2u1jzxU6`q7HN{ zV2RY6ZTIKMynpF_CYLXzDyh7Q!!Q?BOtAGu&e(}F0 ze**%WhG60e(?cb6YMgt9q<(VD85oW$QXFx!0NnegFH$ZI+hn zPUStXLwalVruFU9JQ?-#LgwqQHo<2uZ`skNe!QXa-=X3OEKx@Jnm#8u%mRP%nO9GE zZyWON@f*?omBNm; z?AHhWWc~c5(zW}Gh>%p6>gEZH_pga{H_zVD9b0rrRDNx(+h+j<&;D%Pa|P^d&uUpu z>tBvoz2$zShkbM<=eb+EmhLL;oiXK~M$eHrzPgJC6BrB@zm-?nAHi_vS#7K6%*tJB z=BvbCTe5z6#RvBO)Yp3!eJP87AQ^Yp=hXT~I__Q`m)cYxR55*@a+rU+{L>@c*Zw^< z`Kg_qOKkeG{*;{6of-Pha^G>c0tHVp!U_ zhVS1RLHVVcI$NVpFF0)+{KaCnoAbX5d~3b7{+;UUQZGsLTQg&&DlRoZYi^>c=dhm6CtoVgEQMS^yO-h1KwBP+>Q{zojj(Fx}zW&ge zd1W=n(^H*2wxuUbQZUrwnvmJx(Et2Z5dYNk=dT^`v#i=T+xR!f%pb>2-xWM{PO0#+ zQ*m|fH~FW(R$e zkhIX<8s~hqi4wjqLmzp#O`Yk+S@llL^X~b*SxXHxFRt}Q!imSU8J3$0Z%o_}w7%DltXy!G$N@9PY{ z^w%G(RpEX+>GWI9|LU*GbGXkxdm`4Op?G;I|E@)|Z+a$#eciL5x@S6zNzXDjr315i)vmSQTKFPviu?H_!zRnq8g|JuV$KUOI(>|@se0?ybo)*4 z>G0x@lFR?>JmCf`TMmuju8ScKbTjKyzt9b;Bi-TfelXKVe?r zy|Bi|@U{M*u7#i1Px{EbadSaJ$C_@ZH{SW#nWgQo7ChbB=koM z@%wtr_OI)=dPFi^Ja^YVj1yXdamMNunE}W*C)i`0sshb;Wd8KMfj@FvR z+?a7b?77hPPtW4Eew#Am*IJ#0+nFv1-#3c!`NR5D`_nUp$W0k@9ljg9H(oc<@?GMZ zeWq47ni+e!r%YE(eKmE~k53mPJ3k(tCT+InYymrir{n9Hx;GE_&1*aINGI>{VX-&* z3)d_w&B*=y)K_&{m)oMrD^wH&MXe0j>R-HAX?gQ^;UB{QdEuhV{hF)N8oeJDM;Z#Z zelJy>r|x@`|4C)g$1eF(Ut12RwY}Tud5_trZYyv5oR}yJ#obmj7yn!E{%%;en7^rP zPX}kfOYJH18RRZ780ql2JXPSjV*B1qj@9sV$wr05po@nuJP-NHXA#`3A<*z{MG0@P zi@Ce1)}FHqm_qM7+pDzf%TaHM>P;>aw@yvC!Sb?0#OLSTSiR59jP~mTTKf0+sF_(dr(bgMRjl4XwHC;pJoJy!kKj|AjO)rE`&+?qa^srU) z&rE9Mowek~)tB+A)h>1dOL%|I4_|&|-&F-Q%Y!c7v@8*{*kp6E zP9;M@@Vgxz!TCRWlzeR*SOw)M|M?Z{~Web%HG*IQHv4LtBoc&kRzVKhAv{ zwa+-NSuWS!Fk+@_B-^6m7R`i>{5F$Qte>poII!q?ZPm4VAFjOVt4c2EpCYoxkuM}t zNc`KrU9)4(KeMdYTd}JrQzJB5m`maEkjJIqAd62%wJco8n~BgF@OY`S z{pWhJ>Aq4(6W>iQ(+6<@b2fa=cTWnIJ*^QM(xmTo>*Td3r{q}=sNFK!J8PnNZP@)+ z=W^6)?}trJ6-n^oU)JZZl)H9oh>o^dbo=D`WD&!jq*aISr$$VuTHG&r;PmG^F()f7 z3Ix5Gva(M{8hb>AshK>eGYGLNX3!4&A$}d%v)FN z{kF<&R*1Q8nT=U!d{LKf4 z45e32$y;izkr2NrBzXUhMGGs|K3ZGo(VJ=N>m{=P=Q$ml!$}t|KB+Bzkhpyt`?ly$ z2g-E$bEdzH*{`vsZu0RGo$u>8-$ZCRd^co!acXW>!0Z>L4}XQ{Z;cZ=az^ae(y3<_ zepE=>_CcIy<|TcHNt@P`IewG>q7ap%QGD~luBxp<@|*bVZvSbtDC_%G_q9|}*lpw7_bE!?8sM6Ej_(xVR^3%@zE5TyS4!ThPrCnM-Xfmy9~zpPSY(CF`xv ztBbe(G3{#GbTT^R`_`Ou8%~Aj@Lt=V#go>+Dcjh5^WfdYHH$cBv0o`glZSix~YB&?(&)p>o&u@3m<6hia zv?=bB!FN6fBb#T6->1#_b18pDKzfnaa^EWpm+iKG{v!RY-1o-&d-`6c@4ox3d8@2w zajx`^Cp$e#N|GAdc%FUK{w;O0kM-D-8*1<79ra1X#lMyJWNonvy(cGgb-%q0TUB-SG855lhd;WNEMnN^zF(Jj{@YUq z$7C5E{41Dat09{HKEQ=h(OclB%jcS+X*Ca+N&Ed3NX~C1#t&=8mdGV=w?OWF}NmwIvK|`CL zN5u(^Tn6EEmMks9shSOcZ!!J$=X~-yw1LI%3-1J%E6*pYoV&bv^541FE1chTs_3NM zli6Pw_Xc#xa>lLS2M(WF`RV*d3Dx=LW>LTAClsD!iKqzh+LxZc)^Xp8GiRkO-)z@D zdzM@2da&$I*_s2vpO#ym*l@k8;<@DZdDb&@n`bb-b^EUPmgB&d3x_r(y?Wz+Jpaaq zcif6yy>tDm_Nll0)))G2ozKU1{`>i|c%Cvo{#)N*MzwiIat@?fFwrO(m){}9O#j2L? zW@X(?y(*yo{rW}WplE^TFLt)hjaMm~x4vcWJFXjr>96aKn4EcX-{4GmYEaICZBegu zPVnEK`)<$e^d3mf7miZ^y}SYVQ16D<#V2iWXuW8{kv`PpC>l^^}D0pc0Tgz zbieYDQ|EO_dR+a2a81L&X-C5sDbC=Dc9w4A)X1JXrR2HEF29V9qA^d}T3?ULkg&DEvg8`$f}Z7k^inZ_V7|p;xdw;nR|W?at{f zj@oit%tBxBUYT329@uqK-S%O8i_^-Dov8gf7P|- zjetVyV$TGLvg*Tcy>3lXlw-Kg>9OZUO~pfLBZHy=qwFW!vFC6?Nd;LI9@VUSjQ{DE>jnpxHs`I1S_^le(x0!$bD4jBhi<>!z z@5=4kiN}BPW>mfUyR_>6n`a42;$$D6YfcQ@oLSOrSrd^h)+l4vB>!sLm20ez7d@$* zPlDS2Arnu=8r+?cy?iF<~CA zz`FJtjbFT~%>KRx znd{UJSj*mcUC^JyHX-Akv`~rl!yd2C3iCTWmcFX0(F=J|Zrj6^nksXU&uaP&)=Aq_ z^;&<;%geClVN%gaIb&n^w)%W*!-~@f)#CXkw_MlN%&ua&>_7kL!Hz3;V^#ZZ<-5(Z zEBKOa@=UdqHAQ#bnv)?h)w;2(WTv#FI#P^{y+COo}>DsKIDLqMZ`i!IKP^_cR`ADS6++M z$sIeR4ol2EbDjU>X=_6+8Rv9j!c@#r`UV8AtzG%W^tI>!T6?M?OTJ!S03z;(-rFzx=MA+U++|3)XcEZf(y<2W{&lgbn8FH3!@t32q zN1bf1Jm<~izvI!~>g=gOG#;Y3oe z!%GF-jSW3b8$=RYtW*ND7l()m^lb7^x4&?nhh=rb!{kjd?B}LPEaoVSv^6|)!pbY3 zH}YWG%AB@>^@qNg&Ofvwg-KWBQlE*~-6>P^rfYUupGvWp^tzQ;_iDqw673eh)}KMQ zlc)5|eXZnjQo}st@;-xf^^ypIr$06xmtCxtmb$ShSW{y2PQzn2b{vjzlKsBg#?#JJ zFZL$O?ieNgOz9gOe;s_kUr_A!=~&}r9apm6`*_yYH)&QC(tEQr;`vu-eUJWfjpNum zh1))Bo6a#l{Q6s(ho|uG!#3U+$(<=-_rKojjY#GF5xUUbpW(8o*!O+%Rk!ZS?|oa) zxoVH@8MpSTF58Ze*Mzh_bg=wQ`SUm9!{x&^9=#itPd^plbM;-q-KmF9ZjLM4 zSO5L9T7JI=q%&)E~WwN64~#$pS#l@fDjuT+@Z_VT2c zqoe#dy1?_Wiox0BZtc%Q$l zVPYM6f_sPT+S>{C4lM0l-5|sv>(U;CgSyxRQo_PuGVeEUGHeA6&crnv}xqj!@;W5_9jR`6^}2s%$?ac@)$hLUOi|UVNbM^(`?qzY1mDh<%F4rSM%fiIlYK8r zdMn#pC})w{wTda4MHSm7ru_)!0 z{9F2N-MyB#I?(<7oVdqJBHydA&kvqChtJg5JGT4UmX$G2b3D!mMtVE#)3^R5eKJZg zY0W&D_YM>2i#>je_;CmTyFlP zpUO_Y;SruI5*>9fEE0V2@_S-Y)2nuuD~ug04oA4mozSuCy3#9wP485z{uKE-ZhsPa ziRbQx_c~j>0{8=OIWLVeXj8o?wP)9wr|JCHuH`CAOOyev5#K-3nr3IafRQ`E67TECH?y~*Fk~?pXsee`Pw~Kk% z>&q{!d+$=$();aU;qMidSA3VI#jJDE4_x&-uFUb1?OwLldsp8Tg&jwhESp89Y@vin-l^K79%7gF9i{gvGCuCz5E@5L;IhD8e*<<32KWe(k$ z=sNp%N(^&$z)x+Td2)V}Wh}B6Fh1F^z$eRL;TfCj&pA%rD?C24((vnr>!)854|Z{s(JmJSY=j}#1gmmTCF4RVv?_K-LP6%FZTU*3r6Q)vzs?u6~*FB#H=m- z9MAXnNqoA!?|F>j&H3Gek2ao5t39c{@8J%H+J90f-c8}@`P;OgZQ*mqc)4VyC3793 z4mazB{kb;3)BD5U-Dz{B%ND2yG%+?aI*Q?v_ zuBo48(_4C4Dk|hmR=%Ri?wdTG{koIv1U>u3C!2iaxwrAY#lge3Wx2lC8pY49uW>Nu zPkFQY!spfRXZ|~EGQnzY*(Z(PN#|~S&+6tl=F}bdP1x`SMI*@eDl;B zKVEw&>G$W|vb?MBR_^fPUF3^8wI|=|`gwGYX1Cr}I{jj!PQO| z99Xs=TDL;`xpwK(N9ARyL3gG~mZsXa*C~8S69}&q2;Va64fme4zkB4aDMdaCuGC;s zj8C#VAM#0IBKHaHYm6Eea`(2yF7G>htvHdl=2iD9hrm|ds+tL|9JhE+Z~mpUf4lCh zO~M>$yH@v4U|bpU{=ySgWg?^R4pp>PoiUJJ4?RQSxhBV?nJ%)x&R$<$=2kOD6_DDFUq*^=weZ& zjL5l#{p)U|d`cEQ`9q`RK`ZOViBS>`eM+|0_QiewgUl>VBpJ%ztbG6G$eR9_vre+M z&y_cN#@Qh7#$ktklkBw3-*OM#Qs>N;S7@nz*q3?i#b>6o>!hXg?`>9IU?Fw(+N(~^ zzl`~(HeR;*p0LGiON~`8!{VqjU%q$WtLH2~o_zd}?Ux(EJ}w8(o%(3w`QeWL2OBY+ zFKSXxgctn@-BJIsenV{UnK-_v96f8N7zV@VjT4Ie1Q(t^bXWLI(2hgNx1X+fqrRfX zFJR}9Z}yzu^E3X-T>Q};n_;q#<9f@h9-APoHA2y^tAuk6JownE;%fE-Ifriqf3G~ z7OuZ@YULAumcgC*ap)Ch6D9U4 zm&pxs8D6?tiAj|X-z?_mx_@sF5?)%mRdfEmqV;^Lfsp|jcYMRU7pG-B&a>io&X_W@ zbaI9?W9u!2$$2f)BVCPo&nWI*9wmNNQm@y-d&HuUI!v8XLW^X%ml8@$8Sx(*|@y})NdB&ceFYAsUzU001Wl}?_ zQO@}<&gmr+dY7O2Dw?fTz9eFGjZ%!7aN;bV7B#0Gq3_K0soe})=Q=-M?aTkt;H#S= zoQh3%7pqo1cK;;obab)^^R5$~uY9w%x%X;@ZoYi^tHHO{+;u%#vfZ<$&RO~S;n%6Q zi!MJ7do^#X*1om9fqmEVu6}=iHM&)N`|Th5)0}mxGkyggEb5n7I>q$8r4-MXxD{uA z%{$LoQZn0Ga$QaI`Y*eVE?#xCJL42%Qf7Zrs6fJJ>9j-Y$pS7DnM%5Eu5-J1JLT{VI)EQ}ZIEI&HMS}UQ-q%eG$u-sebJ;4{| z);@RLyNNk;1@nuQRSVqCiHkgFKV=*6CT{9nGxdJ|L&^4yMmW~7v+DIzIMz0v>w}_t%p7)giniX<;vWA%IdA* zx3zLI!TjH@<{M^5afk*ac4lta^U2HY;H6iqXE3jI)G}qaTlwYK>z=lEo=4B6_CMB$ zn`U?OTKqH1rGK_gxY9Z?Jgo6$!Rjl`eX_j2o`r8cbhmqo@T|PKvzI+C+q)ug;+Br- z976BA|Fg?)O|?tzSoKZ9Ic4kd9ggAF-O~M=E|eMg@1A0twC4Gdz&ZQF&RlRi2V94o z6jHYeXWwnTWM{EKm^(N5v!hrKk9QBtuJ_?uhV>JVX2(Xh8MQoQQQXYC+p4$y#YVAR z&jajBQcr|LtP1^BxhAwKaZM;!i-6dbNzN-CEBpRhDBX63|8&?LyC#X2Y2E=Id=3w_ z>V*3Ld~;-(EBXA^mep<%F(*|NsCQ)*bX zXzsqtc3HRf2XFkP7ABsSIE}yh%F2^kbE9Ur-r`zsd&qZ*ZR7OZrS_tZA{Id&3mRs; zdeW$#CSg4B<@4vko~P4aS*(dvKFoG)PtWFzo`hYZPi`(gddyX|;LeRD8tvCkM_OqM zvDyl;9v1M`{%nvh9BBM}X7c=2`!cJGx=iUUIp2MRU-@)0Zuga&d%-9)DXn?k*VnaG zHctWywyap-%cEf(8(`+Grg2Y4f1aX(NS@=vOpel1f7~>rY|IV&0%qK4V~xIj#lhly zl*|#CYn+>9%(%EMcs`scl6Y`*KGXX9r$qA}9?5HeXOq%zAn$Zdce>tXmt9+gUw-Nk zc(ri$<$U{tYGtd>9KOBdB4hPEKrfD{?o@i_d?{Y zkQb|RSU(?d4N*Apti5rD%S`p1w^oE*O;^%-aPpR}hh9|@$CQjsadIM$mz-T_7Abk)!ImkUU*GlEEM~KkooOdg za;&N8)}wuI#N7y1RFxLHkrS__>9Rqd5hKxg9A~g z)uex`|IaoydoW-7ePi{CoEZ}X<9ht-Ev_tk!(6;^b<{=vlQ*jO?FiCk)vpU#5mhNZ iSHvdhobA0yo$dv9zSowk*RUr3kY9HE_*3znj0^xaVu|Ab literal 31500 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 z#0?~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 41c7c071ac75a40a401361571b9fd1358c21cd49..e1c641e3169560539be5957dcd7cb747ecbc277d 100644 GIT binary patch delta 6526 zcmZ2?h<(=~c6Rx04vt3mt&Qwk*%{+DDSn*bn|*a#^&0N|=ZenXn-_IZW3uYXTPoeB zm2@jJ-R`X4xxH-@V>1h5{B*AEjDMx>_XWtF%u7$U$UC!p^%VKN<>!-MTv_dZ^uNY- z#T|^w%#3%pyY6NzWMpLCzI_klE=I#ivb~JYX{#DOgP5AHj{C~tdd77rtEnYVpZG8`_8hS0nXCb_S@QTn=M}b?ZEuh z?%3mZ6vXDZJTc8#AN5B0oHKV=NmOyOguwD!tNtxpob4_X!{5{V`ln@i$K$1`GI3|$ zf4cMR4exB3Ep1NI-0p=fUjOWEpLtll%I)3fGbWdaFZtP9?Q#FcDelPRa?|DKb{wb` zGwHTT)n|TeXTHI^{p3Z#eXiTDy}06L|J(5MVzsWwn2RF*fsZ}rzYf<{tLyTg_VU~J zJiU)TsSV}r&q`XA4jqoQP7Ge88e)3-Rr^(b{)g8SG#B#c2Q9D+YF^OvJ7%u%mI$+} ze)X5G><>*m)@#T!OM~ZHWYmY8i*Kr5Z#*QmXiBTdlZ;;X?aBwYo#~9-V7Pke@|-hk z%f9zoMxMT{7kxH>UG?3uJIj1lo_UkeeDz{l{QNn*_x4p)RvB6RF8TEGYUFpDc_05Y zKmNwkp64RL9lvbH@3@fJ>s@-n9;)!3edld%!C9znSKs;aZur+7kuvvw&O7`xm|2}8 zV!LgNe*)7zp0|hlKIw}o^j6kQ>bbaTQzGZ*B84Kq4~s3{1zo=_Y3W;Iu3jg9u~drP zOs4O|#9lU?tOWC!2cjmIcix+opydC~k>&QWka>4IyS7epnLY1b=cK4qpQq0cTL(TA z)sV2PDJz#U@b9cY@$lm1>XP*lyPM{pdw93)RLsq$)#oO!z1_yPaK&S$Y^m96W9A;? z3z&JGZ^9w@S!d<5_0E+UiKm~e%vqPTiF)AE0Y5j@H z=O)cbi+cL2J0`B0&&AsJ?O~Ecfr}`&%)+%RT-s&^d)`Zq_bPntai_k!EiotI#%Rn z*Ztsr*0@OBHAQ!0#EWT4?-Lp)U09IF|2%BTf)fqyeiI!fcl$&rS=4@ zk;|NtUEI6!3;oXS>z=UvYTGIU5zZ9{F6!*6UM94uOl#|1A>Q~^`?oCBT%6A0`^f2k z*qQwc-p^mb*4VHqW&Ps`+hVnvj~JeI`=ng-jVI*5PaDIF8c(krWNiMIb)L&9?f9)( z^<1j=UL06c_MLM>o9RPtj`w

<)+cl^Ux#rrljU@%!1&=RQ6%)R=bHZ++1Q&Wfbe zyx_Z&)-5fGa~BX=6Hwo{@l7?`vcUcC^wJ)S&Z}K;cESJcEL{zA%jUgfczX2T52#r*uTe{eL)rqYV#%uJaici@0 zhv$xgTf~Q#IXiaUZq9o*e>Y>sLC3hyH}1O4_G-E-aK|$-TPAh#Ba6D8|CKe9YuVy% z*PmPW=pB>L<;Z_CX11?gvE#4VgX#DBAG=FUdlgu-M`PcE)4$xm6&rIYnk~qeIkd=| zx3Xqx{5QMhso%bM)_>Y){O|Yg>5pGe{$KX#HRr$gM}6(@<(<=&EYA}EW6`o`0*B(< z`TqaD-4=d*?d4DXmAkx}<_K{(w@uxp=g{c9WUbKq)we1?{^;5m8I^MHtXuzdrX@c& z_V*sth`jhx#H!$=cmG9$cZqeAY&USbJ#@dZf5GefqTO6y{EJzh#xT7T#M{`)J{ zw@IHVnR8B^IWdk^HD zF+X%yu|ed}wHc1S=11=s^Yj~4{rK0v=ZxgvqlflikcycdZT)n{xtnrrhe; zW3f7F-LV})3!Z4#`3kyMvdmic?zGCKE1dt%oRJ8)YjN%N@i(uozV%_>)a7zQKj8Hx zvlB5F>eXkze(SSxSJmyX=9kQEOx_`Go8x~gMa^_RdQ#`tHu=L6X^R=(F|;+Zd}H%F zZoaR~%3p0pRoE+?#o=0IN*`)UTV-EGRxukFmHU;gF*e!!d*QPcZ|>dUORHzNJwti# zYyS^AVKW3Rl6hV-nzbsMmKnN+cs$GXc=UhecXJ_8r}FyfMJ6StF0c7rS6YZHs$4G`QNJ>r{{CE^Q(8U zWvZX~+Rx^<1#Y`!)t~NmmYZrfu{z^tlzu{yV#23(A%i>0FYfM{+py!`EWY|J=e4CX zeAb6{mO1ckxKti`ka^3cr*9uvG4DO-6Wn0z_9)d#Re8tm#8n z-n&n1YMZBLF>Hy@TgEiiYlApzWLd%LCfx%zlfG-*kUOIoEyNn#ZuzFZ%+*x)*qvQ# z16}zO^o+mVY10#2xTWTw@>BB=Tds#TZ2eM<&I@+R$(_qnX1UN|)$!`p?}rfu$x1qx z_Uwq1EZno`9J2*Gd-c(Ci?aLQGZ={7daE*P65~X{Gim};Wi*T$4VKB=adPcFwqr(Y zxsx*Yu01y|SM2ty)-Aff@OX-Abp4lEGpAO+OW0j!%w08Ct#W^U|IKc7zFk7c67~0P zaK2aV`GL=_vTNq=T~BYW{dI9(<-xwGM%l~H{nni;q;gO87vHPh`RhHW)yLGcR(qX( zHuu*np68EYmCjRB5 zAar2aM$X4Zg~v;)dCvH_ZCK5;=}cCG&cdiUC!(iJ=BgK)bmq-F73*E{XN1cn4y`}Y zS8;o_#}>Xfv);^|{Ccyx=YF;N9eHz)KRBTH>eIs1)%67*gC;MIpSb=|VAnqBuTm{b z`rr0{V=S5eadB=f6K}?;h?9p@wk0?wFa4~xaq$_|jX_S6Zrn&MXVeenQ`vUiWBoPr zlL;5T%T>+oO@EQ|n0ZdrkEPj1Qv$B;Rd3&P`PI$KvAZYL8ztY96HjnoB%kAA;~R8# zmrI=Mv&&V_4((W~S-i4NvuQ-V9+Gf3C#@C$hEZZ}3IWySDwZ>2KxAG+S!eE9XtZTi=uXDxTHw9;Fr!)&U4H735W z?W(HDiq=;QtuayUN>kUTwKmvJ`1r8u|4pU0OR6_~b560^z|}G5c5&9v@K04e34CrF zf)=-Z^QvjO5P5d$(M21w%c^eWWipx89|(~%Gce3@^>3`&y!^-BGx?h*ve~>iIbn(I zA&(bdp6Oj;{!(Hnw|?u#%PB2Zv1MO<_wC4AXm24`tf_TSXZEMWIhz||=3Ywt^Q+*r z#1exijRs2uOH_lOEdO$F#*&EklUd!;O?)gzw*HHhms`C@FVCgov$&AW^d82Am4cC- zt0e0e*=&s4=92JQ%u4yxXaXHs>wLZRWQ->gS6AlzKWtvA)!kwuT_4%_3>HE*U$G1mc5O?6(z8BXIpr3*Brh0x`IU?7wBz> zabh(8>z*5TzwL1eSN+i=XL+MGuUFe!^Z(nEFL!S~xbJ7bS8h+WeMN26x0ip9*PHi9 z%Dj$f3Gu%Z_&)6AJRt@1Bkbv4)Yj<*-QvE~rTx{=nK?(aBxdit6^mjo7tgeM+ zTMKX4=OgS(^2$v6X3XSgZm$SF9~R%A9q}C*0y?WvoT`lMA4M>PQ|7WMO#<~fvhgO#5 z_)a@zu~Ge6ZppO`3wF%2`Rp`PNKe~#~0--&#wC;N@sXtu*?|;ywxxa<_?j@-t znIEqU;5`(nTCrnM=($Zf6>lph1-|#IFRIddc=R5}(TzOQi)HTBtSWor^#?9^9 zT>G|ZR_9NpnX^=`3gz<%t~$L&FfLCdM2JJ;Swll9+`jaS>qA??5IjDZG*MR!FM;kzrTFzZ`G1R^Gq&F z>dZRD{I&PawGUrymHvcpmRzG@=*!rXX(ypcJH_o>GE`7g5`elrG z{>szmuP+d&mY*nSA858~rCIL1%kK~I=Fd3vILLh7s|Pc<-2Dp=^BB0zoV9Irj9pN) zgp=KobK9;7SWmx zXJ4k}3Z1+2*nDNn`7Ve0Ddjv|X}`{#KJb2tG;0ihm{G#)4o&+;UP-L)H zW161>zggZ@oOg4YqoAd))_;-mx#FqbVV>`v-OarwEZ>$_@ldYRYTeBJ>Fmb?*gHyg zYE-TDycsoZg-LOM5?4OY5xe@6;*I>1AKCA{V(O7HbbT^Cw{+qxZ2^FB>|KJn4fbzky67I!zE&MP)jImnQA zeU|yr&@Xj6S7f%;zZ82rtEJ^k$I`y|a^2G!Ve-?SZhbsUxAW({!&0(0>ue4cY1Z`} zSyV2OEV?DDu`lSQXU>b&OuW2aoBKqv%^zRQVmmo4c!gx=wa@_Vnv?R23cWnLB{sTl zI~!EOy#2_v^7f;%78*xRD6*~lC*-&^Ah^$N;gfHlwHC&4=f&zb8rCm+p|m-i;gaY- zyTXFKZ~9L3=eswa3zb~Kx%7tf)#isExn78HeSC0jO6}5ie*WOgseHvB%Z$FQo*4Xb zVU|-qLrpDj_8Qj3J?U}#gU)R6ZY?i8Xx=CG-S+v#wyIu*(!Stb_cEtC@9JSaTh$o7 zfG71{&gMBx^TV&K{}glFtmYP9{l&KueZ_m!xelp+uKbnDeD||J?6OHLJ0nE?f92^b zez7az#LES>*2nboFK1SF4zY8c@yjmcov1AMalMTFpXG}4ord|bGiB56-qG^8_jtACi>^O%cg|dHTWNf< z-f_ClGShRF%sjm&N##~thMGy~dc7i#?*%lk{rH&$Fe*2RGOj zD|ZP;&iT2t>RQO0g-@%h>L}@%{e&`=_{K#+_-JJG(ZVKHOGxa?902o0MY2%=(_WD(8Dy z^UX8YV))bcc+r`95A*KXK`eoVs~vx)DhIFI=j0Q(Dn#ewQSV@$#bwMBUhsr3kWaG6 zNaen?$@NyVi`TVh#R^Hxs*$_r^nP|#u9Gpp>iYBC;w1~Rr)~=Se#T)%p+Q{J;v~Jj zZIWAs-5({FvA*uKT_?S6w?X;!xN9*n%@g_s@;c9C@e0UIR1m!@P`@_AuZ4rn!_hEx z%ZZknBf>^`3G+7}-rXSDF(ERgNOa-41}#tPZAW)Wh{)Z2VZ_Rtd8N~?RzYVq;Kji;(6lOn4vuL>{9WLoe*=rx;d(50vK zkD`i9#k@COdz00uv+aUe(#`lt@A97YY2provvxO5cGZ~u@{-mb^;a_CPhIPdKCM}h zO*PvnajZRe$mfd&biS_KD?f&T_8{YBm*fz7#*NxkgLu z${Qgk&O(;Yd_NL}+E^c(`_#Fw@*7W#HjNMz5nj#{ZlZs$5{k(74PYJuccv9$^I-HR4wryJ~1mApQ|<3Iyz zwy4;Rik@d~6MY0*S04V*7-#se>u##lcAlrx4u~IFKCP-ksk=Tk&{N$#;QnR9o!!$P zJ?ncDaoeP)o~^;m}4d+cXD*NlUS%?6i3=Q6&J zah$Ws<5g#g!_*X?=M#CqE;M@E@8-(Qde=bQA$?l&yX}~jm6~|@w1@w? zcssN0r>jb2y}D(r_1K_bMZHJmrS5XeNr{gbdv;%+$Sho+^WxdU&o$}zefYBeT*wBYm6!D9*(HcslYelgYco7kDBFE4cY`5u1W zxahs5O2$4J_dL6jO~t3PE%qNs6f*x`^P|G(RP;yX*gt_j?9CRMLj5&6cASczpe0v# fYC+UPy}##=zL3^)UhwhHe}*4!H$)SrvNHex-K^IS delta 6514 zcmdmWh<)85c6Rx04vzUM8yeZSvNOhQQv5o>H~Z?g>NVW^&lR1&H!td-#$?r%w^X`M zE9q8dy1iL{b9>t+#%31A`O~?!Gyau|?+=hYnU|hyk#}bI>M8Pj%g-mjxU$;+=zp#4 ziaQvUnHkS+ciqic$jB(Wefu89U5tzyw-@bW+{(hZV!Os+#(9j4^3#tWVN?;T{}*)O zwGPW9QO)ze=X_a_aXIVS{C~XD8ILkfV$9z@?$KS-uRG2gKsumb>sNdgSH$inu z_rio9rW|p!#_jYl+6(y%n2W|1H`)k7PrZqb(bZ1uI zwkOGXn$I4 zci&D&9gEHr**D_0-f*AOF1F^ymS=2+3VvHd|N6RL@3Yt;C&7OGbMZTY-czoy<}TlxHpYA^LXK1+X}uy5m3@lD6xW%$<_t{xW@2UOz=}St%x0g>YuipHw(&q6` z_Tz6Q`R;ZYi0$(!{JwXES$wC&+C!dFv+hpMD-e1VR#Pu@dH4EPg_|w*e70>ry`0TY zU_)Lt$NU2z_wI75kv}WaTE`f1lqdMZU>>;xc33+J6s% z&ovky>9lxRB3^R;(VSVe;)?mJc|#L5gaR5DN0xl|QB8RplC@h^YF|iwrgyO0d5&2} zTK{dGQSW%)K9HA*G4*8JamC!-A#9z=(|Vt{KY1g$qTzF8(xSjqE1Q|w{$8CY+H$6E zt7*Nc*Pe@wk#FA#C-7z;5*N4^+fv)Ma?YzXpQbar+?C(Yem?i{(c}P~-E-rfCJ28x za_Y{qU8=F(FZc8*s6;IM$CP~YJCD!ey1TJwj%nNcc9`w>Kc7>C(fX~;UB*-0e?OY; zIUKyJJ;Qje*xu#l_Z3&|W~`Z_pKIuLFJj-7=~2wJ%Ju6Vd%WGJhfK^iOpA!u(pRYc zDY+xDXTyWbHw#L)v){dAU(S4?sd>+{jk|lzrn2l-+%fskHH%YfM+^T*{Qvwz?KjV! zZU5)Q9=*$|vTXAoLu3Bvz{20T2lV&KAMZEOxw`mAMPSXr>0kTbJWmsG%5k`F(c(H? z>eCOc{cmdhPQQ6Mx&BFV`k(FJ^^ady|Nr>Ob>TnvyJy$!xjQG?=-m~)AB7yQih@p7 z_VfRI-L8IZ?d8w$L8Vh!EL8>Cc(hAn8<^TXqE+vOZ~gq}qiFKxEhqNO?v>ML_4u4D zFWnrtY0+iPk_VHf%Pmg4bNG)+b%J=$q5ci^j@S2Vi;2FN|BU0D<>!R1`knjh_Xqpu zn9q1=G1s5%&>pU+QzBo!$d|3&{qWQUhAk7?E-3CxxU3hHQskboQP9$ZvHL^xjD7Am z^ILX1GibJ~HEf=h*R?ZULN4{ohrjPDXBz+NZmnNvyl2q`3FXsyeJ>e*my{MaeXAA7 zx$t&fZGFDW$u--q7k>X<;`2h`{LH?3?vB9VkFO8y54*uEG-IFhUiHtOEv{uNB<0=O zvyOd{%|50i$8o}TT5$%i&7Q!UGj@kgyMN$ExNCm9t&)|6 zVOwK*3soIXhX0wR)c1+Q#P{xW&m}8`|ID0exL{Y|n(h5Judcp5lP^WIb3*)rYfEz{ z>|9XqZ+89m%%IY*+t#vOX6Ip@wxTC(|2NkyM(tgbBfsR@w;7&sW4^=4!_4`HcTQh^ z&D)ZBJ_cXcT#0mBAM(cK!OvG*)>k%vVM}}RZqA#C^o+Fc&SwK}?%gSS<{!g0L-(rd z^B+X6F;FfzCUJ>5hs!zZ99BTfO$$1&%4%p?0n}euOckr3#D9Qq+sl*)(_R!n0pu zc~6EGWSM=szx;+pzV>keKBfatEYoi~T2=@z$PlU#Rw&nxFOhlqUpjhE%#2mSuctpN zIyEOR>UsV)#ciEe>Zggf+i2A)eZTN&Yute+P6wXwt0wGlzp%T~nz8V&sqDXu`Qc_4 zX2h))dfOnAu=M?^CiaY_r*9uDWvgnQxr`yb=g8?2FSiKew^f!W-8!ME51?xwks>DXJ={j z;x4%ZF==mh^2RDTW&Zr*eky-OmB^t=9ywE{Hiu$cn>lygI2H(&3S7PV{qV*I$6O+o zR2FVFdQ{;$m%V_G?_1Yg*Xwfk854B2-1an4WmZz2;j5r!8IZ!1=wrE~wM(kE&~W#= z7B{hy%FW9^md*VZ^<qCe$5kb^ z@A*FIfo#nu5##Trr#DA`U2OZgNme`cn%~^-(N?M+d#u06UMasHH(BTZj(=R=rc66) z{q?G(*zWB7z`5Vc{)P1XZ?5)no|fCXPhuz2hju2zS@*ZIC-ZC%&amgdeCBEH7pac= z+?%JK=H@DYeO}M=Kt=Nke?8x3)w~nGx0XJryr?DE9~^Lbl2C@Xmcr{dpQ?QGJR4OS ze3ONbr9SF={Y_%V%$|gB)|8o786uswT1?!op)UGQM`h;CyPjnw_A}Jq7_`Jsl>N9Z zd}4;|4bz*}>eti#C)N4>E4XXbf3VT{%2VglVf7CmEmd>huN2?9Sftkcl_`g({B8NS z%rEpFyWjrBB6VTP#!0Q7IR~4Lc|G?{a-Zp)w6sNKN;~&- zomu|%OlzTcaDCGGn{(eCnmfh0JjL(qwW)t5M{=M1*N`69ldw^usVC;)#U){9SIv1M z9s6tv&zkhuXH3_g&Y$)^Cgc0=bnZ8$yEn>ivss(pJ6HTxih6`@@%PKs+q}HzoITg$ z<#m0#+jHmrZeN|Z9MXOg;U>BhE&c|DsQmrrL8um8JXH%Hp(^6N^* zVbKzge;GzTe$<SzmbgusUOh!=lj4yjk~vq`9kPn63QBox$6^$hn7h27`pnOw>&ok9XxghB zdEHj9?qXZPy4Sayw^(-VzOqZRV~xVhAFAKKIXp_5@}0XY`pNkTXD@dDG3pI$i@Umb zdX}Zy#6`J5sdv|Pdv>c#o%{7A92@zK-+YW= z+@Fq^YKZ_%2gi4Yd*i)`uOb5SI_q*`rO{XWvfC~G4J|gB9^iH{ycDb>=>J{vxO<| zSO2X&`*@GP6shm(oGra2E#9~4=fAfnU+&&~aR0ozD%*^a@RLJI(s4DZ1t+}(C_A1@js?4jjI2?soY)ie!z!K z>}Po!{$J2{4ru&Q`L^%W`s!G{McqXf)e8@7n)kD~Js?K0yCwMTjafQV z3zPiU+#2qYD`#F&{Tgr#Z?lfq5CF#{O|hz=l@a_>+h;Edyje?$?N;O zK&oZ4*M|bv)pJsBez^5fW%0ea^-sQp9O~XH*p)1)_uOL7&ycq#rv6hEFw%4`UmrI8 zr-|(A#^vjd=nJL>s!Ao@;|oq_mAyba&Ok=bm^z7Hu23CS$$3<{L#M_(YdCp6aUPv zzg0Yw&)iMe_H(xh&!QC_v)7m>e|C5@-E^(ZRM8pNHm=OO`ThOnTYrVD68&erz|E+Oz!b_ z*<;0)HZMANP3s{~pTgxC3)g%I|1-VBOu9aMOH@sL=G{xzZ=9X?yElJVZ^^pu?N^>Y z&kpF=+kc{CzJ~POklAMMUzR^?GxvE|xKi4`w7{oz@$wysY!Zuod~b*9$*oe29!@a52_2T0Mr&At|i(>v?sh3oinDF4;8w1ttCvN;}sPucddeZ%8C7aDS z)8BoZ9dan$RiXZrH5;pO?X%Pe<(GPy*0F0#Zty)aW&VLS9(Iql=W>O0bFv+-Oqj>` z{OZo;kL;HoiXL-Ze?ccFpXZIaV9FM&3(LRU6v*n}>V5q}q3md)f3NJe>S~MkyHCEC zxO!`gY))U6ZgidfDTkwqzAlD)N?c<+MUx|@8Y`aEJbO=Z*VXx#>n)FUth9eT<)_B) zIqw9{=bT>9F-L7`eb?@D-J4WbtCW9!XZE_2-`RXmLBEyk^)vT3Hz%)PcG(ppviI7O z99{2_S(X}tt>$b=^Y=gLKG5#@Q9kaKl!}qh?^*(X)81!#{_`h>T@)29fl7cen zsYfOJKK<8y{lGr^?bU5XPU2kbFIFduhql%RdYbHyX5>3BF{$ zvGpEr&!*EQmT@b-eY)HzCwFAsGl{jUR9Bsy_t1XTv*yzCxnZ-Hb+1Vaz1eiDEBl3e zu99ne+SY@!gf~W>pBNbz{#cB$chv=kn^qNOZ`O*`N58Q(U}T!xlC11^-T#8Iok@K_ z(*#N1N%NnFo37IRBD=z7j`OioQ|6?_XD*w5%6q@C?QN@VOK)B8VLg0{>(-+vk;6jy z(?4h?l_&+W>6|}g5McZ!EWXga2CLQAKQaGwwak`rec;|AvHjGshxJP{HFh5H(Lbi-(6w&q`Rgi6bDJh~ zGw4dU%`=!iwa+SH?yILYz4PY_`WDt~|J5R!W4`;N*9yZY8*>C!+wJ&b#+y>heEn2W zpT3^vg{N)Dx|j}bSSG3~=9+Ox^RVlJr){4$efId66kfIc$Ihb%Qny=5PD)_do_%)q zBdx0aF;`3u*Ozpc`8qkJ9SJ(Ve)qIgk=6XCKiw)kJMBo#`^4V99DBLMog((`Nf)hq zHgZL6b#Pz#MaAq(Xk#1O(n$BNt+PL7nKq}K*1Xc=@>*+!=)NcX7cG`9aqYRGbURIR zS7UV2>)nTw&R&?Qdh;F5_qwHaP=)z7!s z5m)B^T&)!a*{AkhI^5pA@}*Jx&I)VE-&aqp{1ITf z(41l4zBbcqO@YUZ*T-w7-CBBR_pS%h?%luVea>*+>o&paxMuA8EvFP?k2R(3J)j%V zW|Y4z(y#Hn_N(y9b;;6px$X5Y%6N`j-VDynL>}`5E*W2Lg-@k1KDxJiy1scXYa^#&7Htn>;hqAy1qhEim_eJ|1 zuZZD(endYw!`y9CscPX2#bRay%dYj$7BGI&&Nud#Ry(4?&bx8OwHP~=&4sfwc0UjPx8Cok>oSL9 ze4Db@ZCO`;{&e7Ssf{;ZE1lS4@4y+SEuC~+isi-ewzpIG_SUs1rWne+>ny3sol#Y} z+5GPP`=_hVvObx$^a;bEJ|5{)s+YsKPj@Lq+_0D>-n&P0t#L)yiiW4seceXNz1n$R z2c3?tWqUfkzSqa{1J^_6l|ivb%5{7VdwvzgC+WpBUTb%pH?`H>n zlT+RnnVl2w{ZV))d4|k-bL0<0;)#SOdTp*nnFsPw=A+0R4R~X-7w{%QoV2x|M|T;bZgH^X`4Lf zxH0eh<&WFn$@#q6s--qZYnh$-n_aq_CEq$VsfTL_iXW8@QM_?5%yRw_3s=4F+dF>l zDJ@u2SNd3SOO6urhRY3$>c5=S$v+~0Z+>mpbf}?h^AqC| zo-4k5yVZX2Oo*KE$lb8Np4sH&DWP2{_3?jKO74~NV@qY*|EyVN*Q7m{`ycbS@N(4d zi#V6yls55XXp0nsmekuDVy}||DoPfg7WpzS(3)+cwQizzM!Lx~p~KDTn**aPdnT_i zf4OSK>w963U1lb`PrKle_V#Irf5$S;>?ZFu(qD`{r*~(cyc(f%G%9%&>)iSqPTlRP zp{aLo8?Kxc%ix;vj_n-x!klG`SAFPQQS3hT`e)Jbca57wEst_eSAPEYx6$nS?ics} z-YAgmocGuGSKpC8oDpq5Id>b&+>J1P{CSqQ$Npr$#L$fk(%kvII+SOWAK;&C@J48V z;wNjb+z-c94pm<^zUIIwRyJ?y2L5Raw$*QS;knh<#CT-;mCZgetsI7b&E`rvG_K7l z37y=#EA+)~LF4Z9y0a^`1+)H+6cLTJZhokHGNsLhDNQqC^@an-l1-GlQo4kFWZTZa z>-re}M(=V;>WVciD;4avUMUue{G;9NWyRkVG_UU@=N^&og(-7yElV_E*y8Bbo^L4i zN$+I+g0-tRMJv3U|JKbm=B`<)rToh8z1N>sX}zmp;yTg%TdvjVxYWzbmm<}VN!b4o zJpN&hft}>NJG-W@uE~3Mpw&@S|Ln0R9E|e2v}?AW%>S1te`x>7C$ndCMNY53z+Sc4 zmRGCf&dTGL-cDtck?;16zcl}v=yyT*objf$?Z%o+ntvIr2;j(qMi;ei+ zwRKHV-&-+VSyFA@)*bcLvO85jE@zvUdE>X8VsgMqdlwVC*k0Ye?{rQ)V)6g~%7;~Z zqSo6-CzEUKf2ygp1{TaUD7?L6arBbuwM zY5UAAqgMF&e0#t8;yt4FmyXIGEivertn~3jd-v);tScWqWanBX`tH*In4WzPjaa14 P|L33lU|+b|RCWdc_c_Xu 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;nCi{tVGs-?*sgvTyxSE>%U&8xuraNN6YUIo&JmXw|_gZMfmPsS1GLx z4gcQl<2YGkSFdQ_u!*_q@M?us3*v4(t=MyS)hsFHje*-TzsvU=cYox>9Hv{FuXXL| z7W4OdQMW>;`dq!nrvGOP)9#!vOTT|Q`r15h2g|~RZ}nt%)yvQO>woX_vTYqtpYU3} zj;%`CyKY;bpM8n%+t&N}0Upu+w#V=OQpa%7$@-Jtn_7WWZuevVJ^tDquRPuIE7Mwu zrZVMQ7k9BfHDWiNQDnG(*QaH1FP17zRp?ltrRU$fmI=I(vnv&@%!dRoV z<%zy7MFGaprYg)muK%_DUXRS~mPcb>5j?eb#b<4T>9 za%bm^^qb-hn>R#-`-uuJ(J=AaZ7aMOrM@J#m+NXS}l&W2_%H9nqk-@@qgBuc!%k;uZGQF>{47P zc`{?+jDxqlgq;{?H(Y7hv|sIwsE*mxjO~|Nx_sMC&hgOnaq7Op;VGeE$gKn zdw-r(;bS?qEeZP{-p`2D58zww+E{o_P|3t2<-mr+Y2swYxn-qg1|ak~`%f^rqh_`EJ^tfH?`PmPQn@HENdV ztt_vV{U-Bab;Q9tuk+NcgJ#^>aPr9R57sMut{htA!t_$|+3v|xR|NA4ZG6s}xO2ru zw?d&x&8R6E6A#r1o@n;4{k;0+e)F=gbyc!lYyWq(ym|5Y-SViz`JdY*4}aXGtZrCt z^5fgp^C!YLC%$p0a@r<(G3rKY@1@0jGX?%|@*Ye6pZGH=uQ|YFTjky0dGdGKSFz?) z|DEy0e~0xYv91krCaZ#b7gyPYu}>;UDq0f9KHvVg)~gAbS3f1~tN(LOx|*+zdqwEt zhi_NUpZA{W@$CnPW>@>~6?7C>rCfaao$9Yod7TT_2&7)<|Df6Xo=x;dpX$McH^xTR zZ0FdjebRnkT$dg8;fja)wtZhOJHA-f`qjVI;A@~sef*MuTMZ{_zHjIiQ0i z(7~TSi+88L+o^bEifC3{*5clRCmHYM;%?quoql8Ig2RkoyJFb?YE*|^Z(p{id{tYz z$=kqxI0g(BbSyR*}#$Hev@(_itnVvm*K0mt;`=MDrs;NQ#ly8T3J z?ZnWt1}_rp&h!W0Sl^#}NT<%N{6+j#_G9g@e%W!P?X_96yH4-_P1Vre8C9z1Hd^#m zJzSV7aJTEyzO}iLKlif7wtS8K{oAeZUqV5ZOy!nR`GprxZ;PBN>$2kB|9!bfV_Qu2 ze3D-%dAB2rxuU01#PMP{W1D1Rf#?=~^^pHcmAP$>T39fSN z$=0?!Z{fXkMP}w|@kPgy*B{%M_^{~74fmARk3W`t{2hL8f9?O>>HiLVo&V9`=grdA zSD(L?eEPR7)845&=YOT@t4kJ%R7-f zPVH}&-k)0b^LTKn!mQ(;#4iLttSxw|xt%fiUFW)oYU`I3O}%vO-}dvfeV4wjug!Mn zX3Uo!7Ac<(`SJH5cDob^4;Y{yy6_X33mtpZogXC9CaHug}i==~8&U&DefX zw`^_o>O7cv^UlAjg3^b|xl^|lU8(B2|MIVA{r`uFR!)`7w{FKx-Z6XP zTi>qVh1Zq&&6N&L=lb+PjFtOlY~Y+-RsW_Pf4#r3t)ckO3qQ9|U-o||KQ-JE?$)!3 zwwPaIzT~0f{yX31+HK!=Tx~n+bFtSuc7C0=>-4Mi=^N%Hu1g4tZ~o8N$G0KOQiOp401n!CXaE2J literal 2012 zcmb2|=HOVMvLT#_xj40`EHgPZzC6DuJGDqJtC(SFL~j1=6N3M=xh@8un6>D8ufB9B z$GVpbIcD8q-O2q)@vG!-BW=Tl)3iKqrXTtFUN&fw?#)TXu8g-;PTZY&GkxC7^cM+t z53P7R>r%P21Q`YDkOe=mgOa$LO5wyX59`-Gat*=9YH@)+&zf5?G=k02_&NW+1(Auh^x^vr= zKt7r4DYKS)MJJkM$i^Jmalv%!`vbQ>PyH0I^|{zOwF1_CvkQ{DnzS@HPV*E-E%i#> z`7}mjoyp~si=x9`uuCv|>ujF#q%yBdX3H6gjjW}b-dio+F8{J_UIF77t5q`T69k{n z3FIqMSQ0SlqR+cKPZV};Q9D1w^oYO#>&&eTQ`5aNl>B#RF5Icb>$AnrH|oi$RX$t_ z=eW`wG&h(PPtYuVzB0j0MAA@Gq~b!1f#23i*KSS`?X!KlGFaBf#f|HnQD@mD9pOV9 z%QUAmEly*dU~R8+`m)pWCM{=ECiY7fi)X&*k9hJ^_(17~n9#l2i#n!+EonVd!8T1e zPJ{1~pqoqBikjzMUS6*A-PKnfxv}G9tD#QmCB>?noyv;N>ZhJg<9PZZDR`pyWG$zR zWxk26TX){AJi)PihMTU=W3#Js0^PV2m!wVeeAm_6F1O&)oY}h$mT)kvD{?xpbmfGu z^r#Oyi$x?h`J8-GY`x)h=0lBVcY-ulq;zeLS#ENk>+Hl?>}BQbGdR5F8qPeq1i%TpxPjG`upm`wlK_;snS`j3EDS3bpv>0Omz z4rKCnW)zht&Qr=Pqp zO`W{1IO9~2+C~vm@yKb`XBJOdnc$8N@|GbsvPirpb<|-EXiMKBHY1UlvfbU^? zi1ay$G@qLD*P=H(t=eh&jNx|I0?U&tP0l3drfM#1@O6lGxP9OFo7}V4UZ&C6Gvuc$ z&kSBW)qCZcIhRCshbAr*m@}(3d+EyB>UUQ{>x~_Q{xt4CdFuSdz6C)->$qDun1d`0 zQaG4tct-jqYXEE`tDtg_tl+|Be`QRjsf z-a4nHGxWaJNcTQ!61@`S%-y%;;HNVzhXYj9Cj>72wl=oe>}yeI^_zWfmuOjE>9~}C z%0c)||EZ+A&zz(jCuB)Zo8z3YMAw8@Pw$ZMb>6 z`ii7g;Zvsf&r?~uGW>%Q$D$o`s@DXHY%O2q*ez@FHu~yJ*O!6u=j!9jPoMtW9TEAv zU+8a1Y4PV<(La*Q^ur6qYu_F{dA@4zuMhutUtKL(oS@;q`Q{mQ?W?*rQU15MeivIT zyjUS~&)#l!Y2cg5>;8$BUO#{MMRbnTfoGbjF z;TEl3dwG2?HD#T7lv7sz+em`lmM8szZ|=jxzpt+^>*U=1LT3i+@q0fsy3RW8Nd3)s z{!?M&$~6M18~8tH#(D^FdT4$4oF|yuRO_~^{XpqOS+&c%H5aa(UQl9nV_xnIzDIQ_ zk$dGPW%6(O`P``Wnpwx0GV|Lp7d0}&JuV7N?DFe3x^237!Tj`?$c4|7xp%X;_dR>| zFLZnLR~~EeEf%k9l*BI@h|c};b*J9nb620qIaeQ;-jypygc*R^KV*?@!-{Wld`ol7NzH~o;jyYRo~ zTUPnm-T8qgvTqXa{=ITOBfl!B@`#Cst=UAbspW@f z18!+4Ufz(i8*~Dum>J*v5@{~CIxZotKSle^R%N@?oaD1-0=BU!r`hn?oa6aCPoX{C z#Z#hRzVz>h;1AUj`)b7UTKb-7Ar0hUo2l&S=Ygu z6>ekjVV)^-tpDfIt$E_^r=+^Cty=e-{oAL9WhWS#cEq1`cU$IK`?vV+)OB|r$S+Em z8hf?-RdDFz@7of#&eT8dd@Fui@B0&n`Edu`$)TX>ZupwZ9ZM+b7lk zymj}>;|Hc;fwi(Szx$6Em>tRLI_cy!Y32XhdDCY8+Ps-Vy3xt=i$>>O=QW}wk~?m# wiPkwg@zz%LsXXToWpr7WC4LF{W3l6&ZuK8EnN7X>FaKw{TCqZEp&$bT06G)ljQ{`u 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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

L+1y3z|NObR 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 L_BQS2jqD5np-slY delta 72204 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 W7t(sp3qJn&&+x \ 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 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�rtTjTdTxo?mvuRqCrb`cMk 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

-E?FKN9l)=X`Fne=2{P4E$|9J}+1u$a4AF$wnJRuYkEJ zQZ|VfjPAS>+ugNu)5R6C57K_J2Ygt;{DZyCQv3dUPtRLxVm2&U-(6o(sCcJB(p4`x z_gG|y<{25Yb?1e{&kKt`=j1qlu~6&H*L{~y>s4DNaSMyS2yVZ+-~SP3@cf1%ZiQ<_ z&lqnoWUec?+FKQ?;eKL4(J7gGOopO0+sn3urJgxhs9wXnqH*!1HFmGR3vanD6RXI6 zCpP}6Mz#Y}g);N;V4YQ`LT5|X=X?-3b$)M@_WISE?>I%i<(pFVLi5r5_Z40u)!og~ z;!|6V=l%Np_jFe2x&vtzTYS!LT;e-t+3q=<`zL!GQrA6s>*KX2>mHU%*`6#~6zP?! z_y64Ex7lk>7jp1lI>uGK-aycxm3e`yq=mBrGn2*L_D!OPr8&+kaUbMyak|pKDw4gv zPd#gy_pKYIYwvu%t^eKMxUt#kfJRb^OGSuNz+Rp@-$i^EM4Khp+6teD$2Z@|OW7rA zsA|6JWrmJJ)n51Zws#tbT)aXTFiZ*L(VVwUUAgsq=!6XCq=A5^kvnqcv5U^E zs^;bS1&goQ^gnMt-qY%%wmkFhx)o-k=Q6HHp0&=@xV4aVnUqbVitdMso&A^1Wlu;> ztUJ3fDZ#Uz+tvN!q0@8L2b|{K6@TxY$o|c@kKg2TUDUo%rswG7R}W+Sx6gXk{#*Y3 z{kZq@<({|2+u!v%-Y2~9>L2kfdOgk3U3>oLtX`nVzkg|Hr#SEAL)Q-K?BzSQjcb|A z&3=0?qsjXh{c86pnsZWmao-7_)*DQ7m;e6g&KKXY^C@$$`pjkZHgh&FYt>Q~YUim~ z^!J7G@ejG1XKp@z$FBX|_N<2vvjye#j>}DbdqAUP#j@Zeuhq*E^Cw^ZIMphq&(^D8 z!>26Au$ftV-dvY>^5lG*Z2r~0y*G>Y+1S+9M(n89SZq6g&x@&1=ZZ?+T)kKFJ7WFk z$;P|mgHE)o_1@`b&r#i>vH!cPj{*; zzjWgy%aR&}W3CK$m?LL0Z#A$~oY{Y?ZbtvD4P5j2UuV`i>}kF~J0mkhxUE|_|Cr%Z z#}mt$mX$O39&ot+cJjNui&D~Vw|rS9;^7c(=V7aOf9;tQ@%!)Xua$`Zb^g4(on5_6 zyk?QX=Q9UCctme@>RnMJ5;6Is#fwG*nd;P3+ zp}$F8#^d(a+{H#uB!zhDzZ~-C-@k8fb*Pomojt3VgzJB-TJLS}=*_0J_j96m=Ip+c z^P72kZC#z=%U!7=?1!BVKdxHC^H)zgY;Rw$V10wx`L?qYm-H-d3>K=qZow$q{;~O6 z;xD(H)(c<1oN+9xyz}V>XXQd^)<3B+d*aLGI6L`|RDbv$Ro1a{;?sTqoLg#)>dTjw z9=Y@BQ+kAf=BFhu7nnFt{&DggPs;4SsgJHQpVp4|NZNU_zkk_EwY!&m-uf9W>CQM_ zYdq=ny4>@H^(M1@V_)1_cKDUY*;l`Qd@<;M-gEh?@PiO`rga)AulJgKSzwc>!xc6C z)1~NDnyMWg3od)Jf0;MW!cB7Hapv~t8wI@>yzjksG@g6l0_#`#j&{G7dqkwpm##je z@2|gJzOHu8`G#0yU$@20Gxudr4El6MGJ#iX^Yow%spdbc|Jr8NZ#7L|oMW+ZQnLD+ zAjXAl#!qi#9p6|kkuTD&q~>m$bmC}VxzNe`DGC8nt@oC!Ri5ECG5J%2=5)^q%v0W2 zo?p`-o02+}{g=4c?&djrg5C)Hi`j3p!sm{2Vt1Wv?&C+(gZ4-7&gcJc$8MQjR;W;- z6x`Y)!4l;s=cC>y_9FDx|N3&VmMNFZcXq75yLRccil_1O;|l(+p164B_a#fRBFolj z+iug|f4TFe({)?3>O%>0zdX@;P&|KDPsJYL+rLW8wtd>mtzW-^JKS(y{Ipp???oQ_ z?|FCif?~R0tb*=(Tf3c$K6-2Dm&zYu~k%|7=Webj(t_(ye;i=CfqmcX z{=fH?PWM8+bGOA_SAG2akpEigKjT@RmiD=JKYm`HlKf|8+7=xPN4~mS>+bEJ>d!A9 zFaK`8{h8kS%bA*NieYyqO}AZW>7k!pzj7`7tZSyfW!?7pZ?>J?|K+b7Bu`xmp3wSTYPXCe-r{VSBe}C1)E_kZ-v3K@Wl$RW{K9S3sb*ui*x|h}x3_-{G?^k{* z7QANfVScn&{Hu)d<3lrE7O)AQI{2oAW5=makF=lZNG_>bo&WTvbmM|W)2wo9w2NlX z@=c57{8%tay3*z5-8HkOUqAl8qOxvx{jQw{(q<<=S1t5=6#Sx8??BuwFUub)5=C|f zFQyCBzBfA@*l};Z?%^Uf*ZRQImsu0v9TO4}Yv{I`AnzH@SN}lj`sFDLesk>oeJ*82 zP{5{1GFBX|HemoHK>vsR9xOWWl)^&29brm04e*Pk*Gi$+Jx$;^5YkV|Q z$|L^#c8#e1S+|Mfv$kxc{!CFj?YkDdyF*(x&JzEY>rg0c@?vAhLjE4f$EOb0pEFF- z=~OoQf6b)0v`pyK{`%ejfBg7US;*@?JOA0dpBq0WZ|rBCzoX?`bf>TS&o71t7T8#p zUt;sG3KqCoyIm&#e^r#v=HrHo9+|oeTWK+tsi%4FNe(iRzuEe=PsDiky|$b0e>{A1 zJ$8EC-LI$C?>@Eu_a&!|?7mahw)>_!L~7Ivz#Y)<)^d&++7)UK`n{o!=~^5yNVPfHT7S2}Nv9?Ww(|M;lFV~{C@E*srjiz!sqSx{rmLcS1lvsoBeugvaCxJGiFTJai7$2n6HD~p!=hk z5f8)XG`(U8xg)O+N}iOh;>~z>innZy^p=+!>klk1b9XE{S3mLZ+qj>%{{~$byU}KF z-B>bRZnA9Qn~A4+jxe;(->KwfnaZ8km;a}yL3>``{Nf_puP!ECS7)o%?*0F#>i^r* zNd+-F;%S~Aiv5F4r*gR|%+ohtE`Qi8`g+M{!T;~&_4E0!%e`>OUf7#q=>EalrTz5W zEe0FxPYT)O=iBwY=a;V+%#LH2XY{o7MXYO^xbrg3HIqerUm9MJm~buMP4eV2*)waG z7(}1D>&|gGNax=6sn2>k7fe>GOnmU*wCgc%xw`c174N>sRBsV&tE=v=P7Pu+{u-sK z;Ewl$-`{4Xncqm`IGl9m%EM2~7T*e$(L8tNUWhaw;|rfwl}T?G z=tn)3nflb#(@8w&6RT*W^Gd0VWg!j97Z$D!sB5a5Ic4#RjP?t^WZuu^;uV?5mh!0} zljWHgE3cvdPGj|F8lgue8Wx^f^O9M-{+1)3kjCSa$p-Bf?k$a(|FUL_zEcUY39$D3 z(q)r{ZB=X zomO3-9AhY+JL}-a)5*_TzU|%KRPcf4$MeItr(d5gKYzcDpWOQ^{H#XI+}G>3lsvd( zd+SX7TP4wd!Pg^LU$?A1Sgd_t_NDamxh~U#)yn!$md$G74~deG-ko&e!anPKS*?Q- zoYzvWL{5#_qM>(dN~YV}U(2r?T6NH+Z{t}PpAI%nkGB5;3w1ME^<5LrPnFx9wdlN3 z@A?~7%2#e_P2HXoyw_Pt>g;=s`$i#NOI5QpofB4k;;-MW_KP>HBwTToYG-B4d!Z=9 ze~*vzZr#D`XzdbFc_p4DtS=~GPgSzbg|70~nty*h{eArU@%()5lQWaHyw$kTWyHI7 z{TEK2B|o1k&J3yBqWt9K3;w|653bK_=btVtFroc@|Gd8W9*xN>B<{}_zGxS5X!dHZ z;4d@J>wUcE@=Lx-yZ+!LdGq@m3`{231}PFbLj7zpPb)| zmbC@EiW6{uH9KEtmuunSG_NCv!hSD0_~eMz?#IP8A1&|YWZpk^^Fe)mboRA#tF~@b zdLcL~;+apAu1@spr0I*Uv8tA4#{^34o>6}Aj)U%M`Z`AwmdSfO4v3(;ce??tz4lwOQ$janP@6=z-i50hxNB-@lINJEo;+GA(IjZ=gn@- zCl7E2T4ft;w_28}HK{2ur&1_n$wA55zjHD_imP4LAQBf*>U7dV1>~i)IwnhtQr&*W$U?MI-7zJ~_F3+g?ebS<|12rp{#D{q(o+ z$EfShOS8o8&QtI-{Br3>@SBS(&aes@C>~zIP#Gp;z9)Fz@$Jixu8I<#J9m}h8=h97 z{6ll=Z0f5j_J-|RSTAW9oE+|PaD7pjqNGogfxvlQy~kIsTqtdwd^FBi%Ky`ZS@TZc zkF)!G`|#`AkB`?E>wKL)ef#$5>$~m31Ft0HE!rx5{vr1fn^`mcdbbPJztg%t@#U_m ze^>IyZdLwl)afnp>efeY&%O;DKJo_piq9S2IbZj{?bF+jUad^K%u`rax^Dg*L#=sS z;cKIp|Idv{t*@wwvwKn)>i?{eaY5$pNvq9!X9+8E+0PVtzIEUK_wx1Mxu@1nxo&td zAmT@MO{7^xB)fJ{F3tduIl{dv9gSBBqWyr?R6;OW72 zi)?#We>-q+9~a+og9d}|n@(m1W~61vCceH zZx@l1kuc*x1k;2M&qPh1CD)bTlv>VgC)Kp~#w)gZ{|h^NH$_XR$0x+ReLd}y?tx|w zX8$<}U!(o%*lx)gu+6yfO)0kFMOn+C%Rg5&oC~y2U9vcM5o_wIXg{5g;n(yHK1j`% zyR-X&+-Aj@r#|xcC~NLH8xi)d{(H=6)iaR>|6A&pOkc7|@NSb&^yV93YPXqNq+^;J zHx#lK-&|sH!*a^AGgpoTX6)l?slB)0kh$T9KOTR7-pQSoq2$DL-0jsSKZS$yS5M#T zswDCJ@TK(EXSe0nUQE$(N?zyJ})pyG( za-NZlelxM8bYgwL%0oAvzc z`+lwa`kCs;UvZN^&1`s-+4$q5&b6mI7f&n^HQqAizV7G#<;x4V{xhhb{%3*3-2*A} zougD0-^`!Zky~nGCTiAIY1)NnkifJXp)h}4L3)r$nMgO z<(}J&olGyx)D+pdt}I*cW>`huRNMNyf1gNC^{8L;C_(8M+s0GQ+m@ytFxohg$7;g* zBg{o2D>o#~$>ypFo3tP)evw*Z`_!(F<*T^e%YE86Sc*)_3~1cpCMd`k zlowv{AIk1}%@bt3b1FlaHDyP={&_E+qa`H^H=nmudbNJlzt4ZKx91nXvt{3rw(8pv z(R%fy`oEnkJ=QG$`l{=gR*?W_`iVb|PXc)C4C_4J9Mbw0@+RYw*pAl!y{;+vJ9RJG>ZtD9%)|4aCg;6WkTNA@m`ySrGI9_7Hw&tKkQTTKN{*35~b=t_4e^9*W_EL>iyeZ&%d&D(T|7EHfq0p^t-+P ze-%^7v(k+{xgF9I`b^(mQr^7!a_rRL+ZO9?+>(=t6+e2diCf9?xAmh1w@yZHP;TH8 z{8m(YH867j;n3?|KVn&Cx{6im1%_-u`t(2YV~_ zi8QxzS*j&ERx|dIttR*$A4U-_q3(zbxfOn->hi= zvff*{r@uTlsLsFr$vfj_%>Gl|(^E80ZhNDC=0uviV1Ub(sjH7j?0wjw8nsqu{TY$u z=PF);H|@Ef$6r z&b_x@-~6%bjK1o%Rbks!K6l$2%F%x?m+#4@lqjdvyx%vL>lFlTaZXA<%o<#fy!Q0s zIa~W&F2?mUS(_)Q&ogh{SH`1l;pDr+Gyhz1_reAKv$OSXDxEz)JuTx|u50Cw&&+Dv z@^!U8s{U``S$XVb{S&W5<)Tl~hV>cVFE{bcvQM_SxxPBsK9B9&6UE>2{>s)*dmB=- zR9(DDME1#iHA}8`;q2T`q#Jxf#^ zrnA|nrX@8Sda4H8N!h1vRQvG0$>gx_d7lh*_D|*bp_6NJF*)&G#;p2~q_yYwm%YF9 z<(BZXxrUKXjyAKE&M-f=H6(eFZDEn|iC;74E|6KQvR+NxIcuG3=K1Hb@n@2}9?iTW zvEgit!m@jh1q%YdeOp|o^lMpf_OX)zO&?TCpUvL+hjr<%tPRJV#5b;7rGECRn$xt7 zDu4UqtKZ-5^{TGkTmNs}Tg&bS5371V83X6U4r{54Ph&DGgECvEhDBs94Ud`?615{F zYLiY6|Fnr0^Ok$9p6>Np{ZVFRtCD~25$C6w{<=*voQBpaFRvb}S-`;aXc@cJs>7{+ z1vo?>*YKX#Jki~-{}?}isP@fQC!CMJ=QFwC^yrsEPuN0s>pkMlaYvgEc*Mi z{^;q?!M2Zl=iBYyR$*87@z15J->;v4fBN+I)JdsYp1o%{_bg|aWoaVyN1>%)fzYfI z*RIT9VyItupl(i(;L-^uvDRCE`Yh7fzxKFfO~~4$hz_UUsy}o7{SE!`^7G^M;ivrS zeBadR?RGCc{?dnQtC6nsgtZwLtMz7G;LiD=uJUJQJ%|5R-E{Y&#&u3n4qgJqtrc7` zO_fmf4NZf%-TY)9q*H_MHh3xn; zgU$V~%$IXdImA`1Y)+gso2{dyvuPHuyz|Dwi5}x$yRXWSDvTdunJ^uQLs%|~YB z^0TG(vFnQ%dRz>cZTQeJ@0HSC)-_wE=-b!*{BZgX^WW#bhR3$0^l_hXojLQz zT}lq77pH2tgq+k2z5MimQ<_-4Y;c|0l8iY59Fi_f!MANEDJ@;^)}86NwdvCAFD=Us zD2nslogn1t=5y!!bYC{Vj|Z|t4L3g8@YPo>WbQ7ZnLk3kJ_;>+^GnZsN0+IjlRA!mcB^Ck2WUro7X zT_exdrd_o-_Sidu)ERJQ>rmQ&~J+&?+f#%XLh+H z&1w88%4E{8X*x%!(wTS{8|$hSS8|oN2?uh7xuxbDGUQNr!=#f}Uu54PJu|c6+*sH%2R4nPNdyg#-&|9=^Fdf#ABD_TP_{g%W}CeqVL#JStIQ?)i3%r>;Hdc|Nm4jOFv7KctEkDdJ+ztYTKTns3!|1jMw@&uFR9f1(T(87=@tgQZ74;7D^m|fE;SNZbcl3(8PJ>hQ{-e)?V znejS(g5`#1e(I|l6R*8>U{DUKcUWYX(y-=Oy{p<&NkO$wB0|qkGv@|5E;CTb6ti9D z^Xgj7R>oLv#^LaP4I8V=&m4BMBDdTaF%=05N ztORCt{8%eoE$DZxgz+H#g4-Rr|wm%kXjGMd#VeYTqp?a&7SrJGHWu zW1cZvCg=3G6L!63nW#U-cjHB`+B(qywu?&-g*-cOr`mLmdf;5PTW@lk7dmAd2JMuU zC|ekJnPF#|*0UzFg*|LoBk7uk}iGclK%hm=hN4Ro2E54vhgzu{g4(;6F#?~D({_ZecGeA zE#VB_Z_8tTHrTeDXf@+}D^lX)cv^!DZ=(J6FZ>XM`6lne0@qI+^pz z%^O>{mY!?uZ|G*9v@1HkenZ&@w%bAN3o@7vSv)dVz8&^)_3yK>rrW1K_t*FT9zH{= z#cE^F;`)^R&r_zo40PdH>A2KX{Nsy@k9PO0QT=piXQ{4Ot+Vzloee4KiFPK1wMW*8 zKG?>bF70eN(PXL2EeAcN#QPeK+g7MvuerKSOguY0O7qjJ6EP->&pXY2xP}R&!4!;i+zj^S-lI3=bdqZJ`;hh}4P{W%x5BGn~`t#xA zzpt0|^|`y+c`S^s1b>_J=4o%ZM&#Y6oo33_#gW^8D*Q>cnW@+CAz@9sI;$L$m4o}I zJ?Yy1i_D8(MxLk=Fo|EpCXn(W-9NufGj{308X=YizOgs$%3f_0k#35;T<=!&O-fhu zX@B=EhubDC8~<#H(0?I!?AU|fYd={$)H-&`LhPLC!58<_lfQXu$Mv#$#D|zq{vj=E z(<3TqIbm|_d4W)#vI1kr&X%8fCea;dpK2Z0I4vt&#e2_dPM334KfP~%lTAPK;n)Jz z)NOYhEFX)qF+b&X+{yZH)z{#wb^lJ+m*$(!(qDgCQP#1`u5!_$e4n`%&RIr^e5yV{ z&q8D$@JsFQC<)tNEM%YiY5sv1{#VkYnNG3XlIoLnH&b8(4J&bS6d1Cb9;tBO;PZHm z*4HP8df0{DDxcL8n(iT!$dTl>c&+cp^R^#vJmzuO#4xe;apAn)((atKv(<}#md>uL z7qPpRuesJp&x?gOX;J@#mu|JWn`UpA;?R7sNiiXNg;1DfkLuAS3*TkN9Fyc!clgMo zva?S-p7pj^`=1zxb5X3$SMG}k8-1*XbRc%g3>a5E4Q}1{pHvSNsaOdNH%OAUSHr!AAHM4Np<<__v`Q4ulH7p{mK~r|Nqzm&Mto%GF6Y^O}?3wS*wXwHRG{Ykvrn&md$#u`}~gT z#bpmK7_s^+?DV%6=BxdAhOzM9US&I0;m&%2nLDkU9V_-H?wsB{eT4#}AXC5E^xX=K zzN~+KY}>GBI|v+hZuCy%6>=_vlxxvepMks_lRlU@DvTZ)X1$zFYHd}kgA3Ne{tvSLrn?1{^q zo(aEu716@wwfx-o>0X8}tG#UPa%vyZ?_gUZ5%eOi$`(BsIowD@vsjSBQzx!tWeS2$qtrDYreR+)`yOX5N)4HaD z-a~6QEB@_#&o<>M+nO5TuL_yQ9uGg=@zuW^CbPS^+0~MDxy0;ETIT=%%-*s+RQvk( zncX=nD=!}Itq9*c=l^HDKl}gc)l}8ax!o(yqb9Up?cP6usWVxpx`hS1?>f?V|H)jN zq?bQmq#8}>o5$9$t7V>EX;5s?bw8 z9&&mMkM&uj)ww~Jdt|0;m>8)!>1prn8kMO``9&|!$oe_m-goxry1q$|)gOA5^y$=d ztFm2|%zKh_DKOOZc3k?bsf|CqQxy&}C1f1pJm2@B=An#~lhiV&U4qSQNy=v43$JIT zxb;MG2JL!qVU6yWfUi0K?(A{>H}TmLS8)@oZ9<})2RA8uICL78+)Vk_ZMgH<*|ic+ zC)O8*Zwa+I9U>5_9i`$mm9^nTq43Z0Z(+R$3{Af7p5b+JMa6;5;&L4`b}rj_?cbiG z0#y$$b?nSJa_ouJvMIL4_jmNg{<7bHEJVRz*6-mUKRuiN`PKAyDvWA8*K@zDpL)u_cx}ln+35AnkgbUe_C{uS@Ni*N4l8(J%(W|$ZC^h$^M-Zfq( z|8U~kJxq-WYj0ampQ*~|!c?+v`h8VKD@M=hQfiF0)}glL#Vn`)3Z$(3UM22w^L*K} z=+jT~zt0zccwyVpT?$Kemd1O0=Cra7a&0JD9@EU`mbdiY^phUh-1aA?Pf}x4tc5%# z@zA^lGuTV&)0}mT0@@`m2Tu?w>wEISr}bIFp4P5#mm{n^JYTNfdlBPq#J9~z;B1Ih znMqHtjD}6;=jqOUM`jy;eX-=DBZF!9-Kd#VrNyfX4kug8ys~1tjaUR_^67B zQK`ow`zvMvYU@JGer;YZ&T7Yg_E|3TYW5z*4ws}wYzCSom!-q)XG+8`m{W3y>&f98 zM;HulN>AotIODd)Qc}U;Y4Og7Gy1JI=Npu0zg;LJv&ZT}SMKTeXZAB2ulK#L#4szi zymtAeX;<`J+UlBql=@z(zgf-si*dqJ^P~xarRr0sLc|OVd?n$#rCZ``qa_Gl0+za%on-2)an!M9KG2P2mD)Vhy*zAY~H`kfE%a^QWlYfyRcD6CI zd(piP`(t7o9&$x9Jio)AbL^+)1w-jiob%uB__xeVYnryouB30bV?CvuOPHtsIlCtN zjmyP#?T131bse#HsNLM-_{igrndX7yug)hkj@fChC=w9v(C3Lgk(z#pHR{@j^Nc&W zo(T8Uv$j5LVC-0!S-aIxHS3Xgi%8cI-Y4&xCh$53Tb!1^;clM3X;TBoRk^j^vE1Du zn-#w|ntZjG{KYrs_z{)QUjmP7&aG)vOnH7`yW`9Lz}NkMQ)W-jJ66dhF8j>n@X6~3 zru*Ld9p#zl)1CQ3*2aY?e~;DvyNCZ|=N;B{>|<>D98E)++JEQ*zxN!-aNRIvY==`9{oIQs%T}$@1bL#i*k50uyD9Sz9>A26! z*-X?_>A_x!cQe>TTh4hOQ(J#K=VQP`ja45Xg|s)l<1BEw7h{^C?R)R( z!FPeCoigmMTMC%Bake?vr_5Nv(z9*qHL0Dat{;stV^O}o?fo_B8txJuCp#O35XWpw z$%ip#xucFoFUf7)urnt+Vdg=(gP;HOZ4&F6?{IB8chYg$EgQccNm*E5Bza>sOXk@d-AK);SKYqIYsSD z>nN+W7F6DHp}ho+<8^u1|mEwR3JstFwrRU)FiqWixzyyg1eMVxBNPjP;+X zq2yM?zIHX=mK8z=-X(0h+-KO8@nnD2MJNnirS#VxM8J_b1gZHKPd89nbbH`BB86I%EFR%fsO_V4FE@9lo;TIm0| zQ=H~n$|kg}osc*GeqhGEi{fouryl2>(7ybDdF8%k3eK~RI$Vw_cwjYW!ZR*`4KEjE zY8YHn*SOcZ_N2$jo+Wa-uWt9*yK{N2csJ8+zdO_FPs**evs8UrVtRAh?!{{q-aXlM z?}7dAhqn)ZK5qH<$en2{oDRjNlV=txfBztLb)SXdM3b4C8=F@+e&lE=u{o-I;cxKL zGm}NOU)B8{tl(>>+0-G3LT)*am%{9o!TdHdLl>DlUYlhRy2hg#)5x4SsW@b881DVn=IzW?ypw)N-w%BuS7n@j%x zm??EjaDSVHk$uxDY0XYw$zRsBXSx6GX<=L8s_>HG=u1xT|B`2$KfbGw2*1;@rXSW_O6!EJyz}7_uAq9wyo8NH+Wud-nepu zl%bcbj$zr#$~D^;EIcl$*+AH^)bpl*?u_}J{7OH0L_(mIJg zcfOj&C6jacXKYPb`|rD)S)Z=W7W?||uiZB`Oj{W1Vcwye-2Lv*=G_f!5~}g+a#4l@p9-JYSTy^VOPPN!*Eh zYfbBUrBwYSr%vp?z;{10@~NP$$oh#+sxu#Q%YU6k-^8>L^7V{ zoVqFD9VAy0{l@D_>u1aKmtPW?TK#tU-D|qh`ieIyyESP^q`GQh;B?{S)%Vu?W_$G4 z)zbTp-rcfhmdG_xl~tijJXU(CYBng(-sfV^f3(T_&7Extl|mO6Pp#7GF}Qsv@LAf_ z6YNPfhfdkJ_Wr29{rGsjo{+>v1@;BIgLlTKaCP-%7QHPGdL;6(qs054p_I_(y&O9# zIUPRopS4-g_EeL*KR85c@4+CJ=?=Ff!+mrZuBR=qeSe~@;P;iiaXZgUE7hLnRpIZW z-QrfX@A)j|y|y{KPQTwgFWWdO(bT{(Kw?^_rT!X9Onh7rq(%OZDHLyWcIm zwr_g;WLEy=lFd)vzS@(k&by#j(JMn>4b#)PED?-T0yj>+ko`h&`vjq+B}}h-blMvQ=kiPs`=LU)6S&uuancPble$FcpYuH+U zFV5?w;O3=AZf-Fb+<*DU+%i@jUd3Xm%W+3isE#>9m|fC(^#_?bjg7 zlReAhv})e5cc`S;hq<)AzgFsMQ~&G3+ovCYzWw;~bNltB@{$4K+>%FE-Z3*|Vu@l4 zYPVEeaKcdhU0=~xpT3D}G|YK>ZLXe?>6SE~P~Q-j;`6YrHn3&d4!NfFJ0cWH+T^6) zIsAzt`4KD&?jTn{X4~#6Krfa)Nz~ zdo5-SxJ`1|wu^XWX#TJ7R=1Nd7nYx8Ztbz?>4jHT1x>|Io# zSNP8T{dVK}Y3B_5mZbB2e^BmYmnLAf>8R*p-y4f=1fBRUr)F9><(nvLrZlg@PAO5H zwUV--ey4mV&t7+>_qJH@tc_xV3pKs7?Nr___`!SkLhrR*oMlp9a;-cQopf)PJ~6&E zr71s~zf^{Ky+)#6wttDvNu?E2G~F~B;~4$)c4e%aw63t_X1($k$In0OIr1jy=?FjB z@!Z-pFnfyqx32b3y%oQ;@5I_3<4Wp~bnfF_mbv?qL%e-$)gQardL!Z}3&QjG8RKMe}X4UsOz3kT)@01dkX}~zon#qYy% z-*j{}&!57l=eB;BV;=T=*T;V;+|RQvp3Hu7(cewudPC6rD`&p9oA+!C_b=p(oMq>+ zcXN?TV8z2vI_*C7h_zT&s^t<>2a$MtV%B>UN4cRRkR?#CCSc(+Bh_Z;`%XWf}%&^?h=>&?pBT>H0H z9zVI^%$9{tPA7J<&aX6J}OdhFqFYVFX5qJB(da3=NZvWN({<*t6O@u@yybVN}AAnWG?Hv3tATs2R=A- zc|Ch*#ey09>q7;Q_UVm^>e@sR2)@kPoqc8H$ zNlCKJp1ku?*VWRE@!`sqhg=)QUy8q7x?*=;jP_=>1D4nB96A4Wt5oU5yK(0>Zom9( zbF5wNn?(3B5P};M1Ki^8O!DpTF%>eXsof zox88Tii`heS$^q{{{BFo3r6)_e4JXWK_1*!7H3(M2H*Mo$8FA!{~ym+?%gr(@=MXR z4_g_srgNyTj^~FU*vj{LQFRY&!dv`8L}>Z{A}QJ#V-DukZ6t zY?t@HFTTXZpfO^t_+nco9@O{Rd53hPe zBpfOXZfFI!*aS`Ux_(c_r#*Or`ollkbFw8C*@#59gk7naP;VsCSi{!9_Oewxvht1p zeX+`{>$_fFb#R+J-Pz)koApHpBSYnXJV(wSZJ9XNoV~PDl6@cN&WK&zX8xZz9{vBo zc<=PaX05|>=ieyZAnka*(fjQ)-fv11mMoHOj+K1n)uzZ37htxh%vgV3)%54yru)N0 zvyJ}VWjrGMDPhvFH?ODE2bw6(+i-brAb&ulhTGezZ!RrtJh*pVVxF4R6ke5g({`L! z)Kr-ErQBCIT}~|f^oEF8?MG*|9-Sd~vT6Rt`ghx1UAorHG-&*vEjfL1RNUMDcf-g059w8Wrn}vN2Jb{d4GN4zvrBob@q1so!)7$ zf9~wOdq84yxW^O&^W)!yzfG#pI$3i4lK;;`wUs}<|2|)A9Q8is{(}8mXW20_+TIAu zGYi>l;v_aB(x`H`Nnc^ztaXd{)_oU~+?>2($(j3dO_~$iv>pn^YTme-s>UdKe(%Mp zl>u&Fe6HO}-d?ofv*5$!r#Z4td4FFc+r4$Vx+SA{z5D$Y2e-EUv^V{k=i7Dv=_SU^ z-xpp~x_Gj;M`oT{;J)D0dojo3uKs)cTz~&rN%w-sR#$W%7R_5R`(v5Fp>rLz%D0NY z+)i7e&R!Vg!o+`QpONxWo@wqP%nJj{1%x~M`W${qUY1<{_;SI;; z&nN1W%D6IZTRxl>R?y>kHf#Pe?OT?~-+!ysPVr6CZteZ!#&zH05{m)zBA4k+7K!)j zw9XimOq^3$GbN>S@0b3xmlyBJuXXz!KQC^c+`Q?H&OUkDybNBI#MIY6kYW?&Q|ac? zdj0iWuNci4yO#e6*>YsP|1^=uJN0Kvm;SADO?!7bXijii{-*6B zuedDJ_P9TMkSf{x_wcPwhqvEriS^i22XUw^*) z&E-3~8}eq(=U;BqUm3>z#OlYSp4lxaN%y8$Ml!zhRe4l+?~XuuXa&cUN5Y@ewfAy$ z)o(GnvBl53Ohu3T`)!wy&2^$ZGn}XGVcd7wMRxCM-3cBx6Iqu(TjKHLlVY@Z&;He{ zzqbFre*CxPj#&$9+&)#W{>-Jc>8*ibU}M>nM{_QpSoE!`wsGe!;gL_NE_v#Be z&TsCyuJkg)sKR!8Mtu*z(o~y&)w_YQ5JbD1S6yD6t@#lJ_sAK6~( zOL`Zdd@Zs0^v3t~oYqfw`IzmU?_gmy_j}Bvlg|t#UK~Aqu6wq$5KqbL*v}_fr%wGE zV$Ha`YsV6=wY6%;LS#Ab^}!PFrrs!S}TFb@kqr%<1;^ANXypE38(X z=%4F%L@hk2@J-?irGqU&B3mloM6A;BoY-_a`tWM;UAlrwzN>lDCK>fBzBs;7-YN9n zn*Uz~y^R=HzA%bDj_{v!pl|Qp`RX_BylZ}I5k7PIn}Wkm^1CPRVV$z+w3D0j<^Oq0 zt7~TezU!>*_xkT{hnz1F%nI8lZM3RqaJAih@YqB5ELQ(7t?fH43TLk5KmK%jcJqn; z|3CUuU0pN64lMBBYM(b(f?3{g>h8H`T#Qt0%WJ-!`1ba~!s3FC)zc%>f->5pkNiC` z!%60ZEth(uWZ9MsRWr8bXZMyD+8CYIQ@)+wcWI8Ul|0+jO~H5S?)-f2`fmNZ*T=8_ zep){(^4ryaLhT81JA3=Z{KFJGZwA?&6aRH{N$Tbolf5=xiu$3XTdi!-Q+7S3S;L=N6Y9^|V{x_VVKb`^AmTYC<=4E>7uvYP(K6?P%`b^7r+>3M1-Xt7^Ws zoZ2L_xaE}A;e>=&C4nnDIZQHs7iqkl6zu5cSETJ<|HP{&x$)67ZSCrNr=DMLZ{O~E z{H4Ti)en=kXZeVFw!O1?SevQd{nU7uQK7_XsbYx}ojgwrF2^?K7Fce4AGG(yujAQs zJU(|6zkReTpzK@m(`QGo7yiB0(Dvuw%ct9)YkM?j-rv0V=EMuqONxBfG4D%0?s;6e z=xOX0{l{iHQ?~WjU-4MRllUw|iTjPeszdzyV{4l&onQ*+1P4~*IT)C{Qlx3~*m8pRe(#cV#?ALBp8@*aTgHIxQ=7*>2zNdyx%YXd( zzz3yY>1L%-5=jSkZ8AL?r_f4G!WQW)iI>Gu85HgzqA&iiV{bDI<7Lw`TH z(j(pye^FTOgs0av>$UUBre%h|sj_M<+-&JBT6QXJn%<3;4^_`T{rFm!cxB~{nU~H? z`8iok^l|%FJ=yy+b^k9vv1_&JuY&(yPWP|>EWtR1b;*k&i_0^(=5PNo-&FX?^>;je z=j$c?OfPCOv1-;-Oiy2yV?0G$G40=}$(d}$Q?LB*4cc#aM}JAtr8z8|_vg1>cd%Ce zFx%m7kXKt%7w3u<&%2_1p7cwl&$gX@@BxEoIaioE-;UTl{POeT_QijVdl(?<{?Nv7 z!GpxO4<)sx^wd_&T6m{vs`%-1Rg-Rbw zezGpS+i@qMXaV2BMwPg=)74eVwm5G)FJiGy zd+MeYpBD>UxnNsAZ9>$Km97kzq*>mmS#JF(!*n6}{Hxx-zkYn#rVy;qVYqG;^Gt~c z=cYx<3op}`2+w|y<8wcK(f31(q?^_$Thr`{M(z0j_2qeQ59|AXm;e9s;dcH0eDAWk*-2^>&t%WG_&I+?_lNqtlXiACkI%2y zm#^2^%$_^#`urP4yxiB-Bp>PQ%im?K_u<-A1^w+WeLNNh#ujP5Ht=IQ?)tDawc+m> z_l;_5p65=^D*t+R_x}&K5C63n|9tEFxxaZk>mF^ZTUWL2;7jh)lWn$p?`+zZz14pH ztaE|K>a5StKmPjtd(ngh(mN)hZ() z#Zq2T{WW!2qQaMss6S1azI#VDyXyjT5rw)tMc!Nc zDZc)=R{RFr3471-7+zUyDCj@a(obQI!$wnsheywa88b$lIKKPk9rkV8HggIa@AQto zU3h59^WYWVPycy(+2)MI_7K4jNfE4q8LJzwS_GCo%ZPX(a-vc|O6-fwBeVV08=p_l zjyPCIaS8)R|Q0G=?KcK^nP&mIt z;-H;4Uv){ThnjPJSmrv>H8vN8P8v!tH;}1(5OJ9O-wdHB8)dm^m!8Zx$Nz*ei0$;1 zr7w1SG&LL#idMIj`aW^PX}4<`4>=>+T@8goau>yLWw*O=uG!3KJ?Z&-b?a9X-EIkg z@VqQ~N-%oH79ZJ5o=UMbn=T5uEmKs*XEl6WJEHDy@RS(Vi`&Sl%Z=_QA6UDZLMuPM+{;UL2pqblD|bCwk8GvRG-2p5oKORfRG0 z%@s}@J9#2>=Kj4p9RU-c%WwOl{n=<=b5WDd=8xZUceisbRW~S{>0ULV^yKoKB##rV zN}0ce+wO#${@UYn&{XfYn5MkBKS!Wk-ln?Q&sN@^zoW(Zq1~PR`}Y0$_E1ZFB4=ms z@=LP!r`-N+U;mBm*-aL;ig!K1os-HRGj1xcEWdK})vap#Quq3IXJhW3K0f{Y`Tl%; z?;F?moxIvq8K&VMw~bG7=lQIik#BCsn`z#-+p|x@JkWvru87)#W=j zpKx5pwt?r-c?-?!cem}n$X?o1|I_D7wCBo)Qzo&99zNz8`giJ?4$+c*(@X7j%9cgD z@5*~ywl;CoH{q){KE2VqXH%w{@cGZ{)32}p-hSNjk(`N*OW@HZ0;i9jta_ zy8}~`^iNGV$y6WI|M5(GLpEFg*(*OUCin|%bh^1TjbFoc^HQ-b1`q z+}m3?V)qL5b3B@GbLK|X!iT2TlfL+_JL1>)FS%~gu2SpEhqx^s#@(~|_xJMe=jT`N z>0xc?HJA~?IHQ1jJMRqrjk03fHJ#)=FS9<NhSO7qpKnzwytrDRNwv- z50%;x7qYf(ty-lP74t%+V;$JAcpY)_%LX zy2{VrDswhUPm}+Z`g8vb!=n=P+ZuTgmP=X}mRe&3lAm>2WP>0LUvYNy!U zt39(64?c)sd6&&qsIJ|;Wm+dk&IFk+Zd&ymYDTBh+0stAPx4-LY{`iOb;$xhTug2n z$ew9AcJH*zw6|q7v$FiRZdrCtGktbf_0L^N+qFa<>nd%L&uOw@5zI~V;Njacr#j$J6AE-C)rDi(?@Ng z;^ZKvEh%rs1D1cAW~0|{#yU^lC(_)|z{YFNX@!{*{=e?z3)pe}=RCb=+d8gYPPS~t zQlTkFc;5T$YC3kr>Dn%Zti;VGtNa(=G!$Lh;AA^#iF02^{lVx@JBp{Q-B!QitNY*i z$B+BV%m3eKwn^ZR^@QNP9Xa>qm-?k|IlIB;rMJ74*)yN)RcuT~X-{%wY+GM4B<0pI zr{`wc=-*&s+s(e-K+Ao?j9;4ST$V{1mx_MA;uD*-!_MdN*G~b}Ur(uo{D0N*!Qr-a z%Fj4i?e+1q^(KER7vEGb@7E0E-abgZtWm%eOV(ouh*jc zK%?Mxj(ZWdmZzsqJpAm;mtEY;OZMKp5}2d&m{m1;l76_6=hsHI%4pslf9t;|%L{xn zE~tL%I;pfkg3+iaR><~6Ozw0u?|Bv_GNuhClj{AqpPM8e%Mcu3dG1o}lZSK9w(R(P z(d316gt@e)fX4R*#|;KALNzV-Z<-UY_&Vp%xiuYor*1KnWac|8X1uL*nw1H&tJ%jH z#q4HF9_yT);pyUUm44Ex^NHq3E&Z^1)oo$@$2FIRx|p>`X_ZMGeY5?E2G4|x7Mnk8 zUt&9do_QhPrb{8ur>A+dzdYlvcdo18$ITu0zRo?PoVZ)jFTd-V#@mAG6FNIzHpJJ} zRDI8T$|~VAb?=3(4$g5s>>I!JH*Y!P;mYRtf;G^^%-b%eW$lBciTez$O^LZUseCe1 zYhyi2p!we?3G-JsMfu+P#L4*C*~HP#TkhxfLr>gFGZRiMY%Nydv=P&{(CAkdk_?IH zx!fmo_>xHLTkXetR=$vZyCOYh?w$+H54BRRhFBF!3s?moU(=`eHtzIaF0~~yrcCkB z40GbK(Lb)k+1RXi^3wFz4^K7U{BdLBm$f~@4lGWw^^cDxEwtR_*}M8;$OZYfk3CHv zrHVAHSBiWN@Cn+G=+J%8Ky~fuVrF;8sR7C6Nirt6Tba*_%oAgLxml}RZI;95Mg>U| z?HPL0Pn^lz(8IHEO00Lxi>2~rlT^xuGfy9zqw;BA(%Ho!)khoxn@;RAn6cP+({@d_ zeO^A(R<(pyWUj5Rso8FQd|lq`p5$4ZLU$brzx?RXWG{c?;G1EwuQuhWHHuGN;%)Zj z@W;AI|9aK31zzZ!IhV0Da`CeHtEE^L>K+zb6r#Vz{>s0`iFdv|T)I_Q;B1laq9ZX5 zdViTtoP3edqRho}yXmde^NNV=AJP*U6bjnz9gYpuUgeY$IJd9B^eRk>C-rd_}CRQc4iH(RWB z+m@9I+8+3PKeM{-^UeCoKbb$Ty52i^;Cl+=#tRb{uAO}@Fn{Cg9wXkg>S>pBrzT7| z_pHfus^p0TT^^m8S=OJG6Du8;xYrw==bySZ^2PMy)2El7;8}T{i~TvXqRxVe+2L+n z{NLwxN(UV|HsxWX{3Q1!Ey(1>Fn*Q_JQSDq|ACwZ&jL|{_Tr5moAeD@V?n(VA+I;^N`6m@@bxG~0}{L7h? z`adaeOr}I9B)k+B5Pi9Ei(043gWR_ru59V0SuSFQn+!{Rd$iNj{gz!!FB6vt+;LTh zg-vyqMW0H?er_{^w4jS0onv}5T2JXo^)yXP;VpbrAu;3kg|8W_S-)LMn7hXGQ03tb zb46LZZg1;6`fZ)g!WEe}FP|3bxMh|u_~ukZc~^Z>f&JXf6sHp3nG>CgV?J-5-`c?6 zcWKLo&~pimrjvu0-&{MTrH@B_nM~-tmka+_e4h5^fA`Pyww&WtHt}@3;0pJ$;Q&xUTD}A=lRReOJTR zd5gb|3}qAF^}b&Do>$@_@g0U9mxS zv(ZHJ)a2^hX;NlSLSM%1HhN!soZnx5`hxE{cjg=3|0*>j)In_j#MNR4_vvihJ@rQA z<&{>Gs@$G*mTMWDTK#C%mfMHkO;3ov^7pk-nptb(MCqk(L~GVg`d7by#ho|%w+HO# zOuAUR+Ro0tuHxV8$NzUp1x`>=dbzAZMo=+{Z}H>>kqS$HbjUEbK22bdo)K$!;$Q8$ zZxhrkpKTU2{+gcC%o4D*`l8pAu${b$CzGsL723=s9(=oVKfrp1clJ4F<0MZ8`~3aK z_MG!nSDvwc!`d_NF67Gk8NI&pNwsgzxz`r5OIiPV!4u3xUygWNu z?d!YM4_Eqpyf@uGh*7(Ka)oA{pO13i#V%VhL)oei4~mFgXD!F~ zhKc9bRaE>wJ>8!_-`u0-!gZxJUH4`kax0yFK4e8&@MX>{wfVW5kFC79_t&cJ{NDSN zPqBB_DH?Yz6P7R$de{}S`jl$Z^c(qsNf!*8tmEqM*43!)i?*J)WLcNMv3k2dBKOKS zUj1hJ{k>00^y~c|UxdC~ea&g2`R7H%7xTK$*ESX=&)PIKH2%-Blil&cySbWeet&2C zyYW!v^ojGFQgip0@0xVg!sov99FJ&&`ytxeii}QoPf7lMZ~cicA=JV4q>#lE70$hN z$|lpUTquxD(>t15Y7=H6zgDhnZS0r3^;S1a)m~;#TEA78BQkuq)Pf05x|dbj`Sh3+ zggK?u6jGLl^PgyILVq>^2p4$V%PWl6STA6SMzsI--@X*hQDHF?~?g({lzJ^JJ;Px zzwM|md0m+5zCWSr^6A6;t1U84`WhVYu$fUa(RIu2$-!G*?>+H0c=Pwb6*Ct;XAr;t z^z++$;rI6%uTSZIA^uMMOSU%RR{dw}kcGl`Zv$A2gPz&y7g0l3a3&<-70+ z6XDCPfvr?d+N)QP*4-r_L0OuUq`8n*t+? z=S_<==2!agKEc$_@qiyme?&%M^8iFrRIyz0_g-fTBcp6v8mSaccG8^0Ly(C0J^!g4R=*`$H=IULq zvSr1ExTdRJ|Be++`Mf~(2k)_KT5HM<7sl{pFn4ks}cbvnFudW8Jcc$w#J9Bmn{rdcVdp(z{u7?3A8i$>_v)wc-xA z`Ri|=y{Y$MrnH#UGGix4;b#5+&7b~0Y%k~6HoL`mn+0A3j;^g=eN_MI zKDpv;-x7OR!<@gQd~kj2zBg%~iP5r@Cq5}g@_LsNH#4lPSU69LvuvZo{u%pjsl{TF>ryN~C|E~5DG+wQFCH4vSz%JHDp?$0 z$;0rW;Qqlzi&)gS9sfRCE{Yq(Az2oq~MyZixrTX0MlP+wvVEW2>xB1LY%?sy4G&=&0 zPFG4*)vKPhL$X-OT>0vA(VU=_k8WtZZNJ@QX650wZl}g)j%MT9qd_Nn6@D)MI5$xK zQ*zt6*sAcHqY;^Y>yHUUb|@S7&FraR`}D4QvC{ElL8;PBOH@=0uJnZ1e0rzI^}qOy zVP#Aom%!!v$K0E5tnWE}Tl>`VuLcY`DxEWI&)B_vo%`^zm(#1dEFKZt;<-0Xm*0~R zQHW^OIKpw5VadTE+!3W4(v9>nwKX$MO(cfpr>=_yho-Ab8!tPeKi?^gB^R?Aqo=LXAyxhc90ul2Vw)E6yU&1&J09#rnNf-zvm z`V*N35yA?p4ABmv`p0juZQ5sD<{xolBkPjtOG}@sm0FlFFdvw-=CG8*mi6+Io~PE& z=Xmt+xVXEQUCQruCSD@HKl%R9xX+@x{k+|V?oXTj?|(?!ns4r8q1-;ZHSc>@MkcSi zHsjM;!=oz=TceXdZ9n#8tzl)h&pvZCd(&krj!jv1Ol9vh=g{P=ET2WD*BXrO%$mI0 zRJ}ag@87jKG5LNOm9-9%%h;}hQRp(ZsmsA=8Qau6UaiPxuWJkHFRgWa8r{69Ek$9! zk7@r(M@=Ia<&y^4LGP|DxwF&!wyP)GJ!v5&REFtaKWs%8y>RxH)zh=`|M`1aMr9f?`;l5CHAarnfg-wT#xc$ zE%m)o9rNSu_V`Oz-q`rrAU{ju)|5-rBp+yToM5Qx>tej*!xA&s;g{ZxbcQ6Jde%nH zL$j9&^_p|ei;!eH9`fwPbICs(Tve>Aj~Be#DR6YsMXQNvvz7^;OrID0f92{p-6#KT z{(OCS`u2JM`C_*l3*7ZtW^Q2;__s;<;*Hg2b9zP~8 zp=jG-@qTXE&hO{;SenfZcUr@C>azAR{pe2@>UA2XUtVQ=cEe}g`WKZ)<=hvqQAihg z`XM+^a{7%P7sYRj-_CozWs+{>jzbwvSHhaIy*JO$Kk2%tT>Q`_C-x<2n#{aM4j0w> zJjnKEKV^9>?L~gx#aMadGQ2xXBrAEd-b|R;8@EZ@v4C2RHCx9pc&q=f6I`zU`=SXk9~NA}vs zR%PaiuVNltidB*@n(jU6=OoE#j`FXb7u*nOG+Nwv$1qdAdu6fMnc7_oww?QCqUN74 z;Sk5l4T~7^_e+1@rBr_EE6e(mk)_-*%13hk26pY|S*P{=;H;d7Tr7zupZ*%`c08*p zX~7a@;a;hAW6n;2C2C(6&aAJsOKKHZ^yV?U>ualt6|1j`mE<>`uQZ4}B79hf;bJq3 z`NnxG)ZNXmEsjxdb1Xz4XXo$v=u8w7*VVdgS&SkLzCrZ-*#s zKItHPcLArem)@+evpOg7rzALKR;LD;%-om0&f0`Y(pUGctLW~nN-Fisj%`q$Tpw#} z`60Z$YOyLPdh+2%hS9T&uUYN98E&1v`ZCj^h}q1Wmrt|JD17ly#e7d~@1jKS zO98qXYA4vdwyK#~r(BMjx4B@ihLucqrC31yOWh|&zHf6+Z!)!8GwICF)Qcyw>X^7U z{8jWai)8-d6tju-)XigRFW5~T*b-h!ht8<{(Yt})^1j!fUlL#Yr_T=$(JI;1F=6SY zv{~sbD=Yp^{quVEDES{!Cu7X7Zp+JpP8{j{3jB1O9oZ#UM9$+|b^xz4=A z;Dc-p+-db?PPHc)Pbc%rIIHY9a54VE8=D@HK+aRKK6}o&w094J@|LiT&-TvyXnS)OUbphs)GK( zSDAko=9TKY6D+he|#{fu4K=PouKzPd!Uv0ri4 zpO&8Z8*?7K6j`lVJMWB8>D8G@7L%6#aWU}B6}kM=;!=a?Q^iil>yfLfSc5-S?m2fa z@%`VaexIK`{rKKnBUydVk$Ryiv;8h#D*Tfb(O2|&<&Bz@!`tN!C0q>U6_oovrGsVv zsi{+D2QtoP(GV3d3}JOrd2Gt#79Y&J=falBx+|_9c@ZWw{gb4~wRIv*w)ZBf=$JIm z?2+t?S+FcztG!rZ@|so@}zY`E)m-l?lWs=lr>RL_5_=$jlU+?K5Y& zo3!LK*ysP``hQB>&SuZu4W4V97QEW-wB*pYdYh0Jm)2joqi0nhpR;4_PS*P-rSqS; zKf1ep)t7vK`TMs2-<~d7En)tuy5{{Gj+yHcRv!4!8>{+C%y#{pLw~HMuGf&&CW#Ibp)tWg6 zCD>>8Y*al|zsxPPeVND>>!0FD6WD#tB%|5R*4=D!+ABLXbn1mXZpQv)Yjr<#zVS>k zS5zr_bD&C~bJm8nmL99SjVCYv&z=~k5_Em(l+5Nw!dKTP+AANGYfyf>Pa-pPv!%(= zzO|lWLa!}_O@FRCadgR^-M8oI7t9q~wQ*@BtAS*7)`V+@(pTJ|C&~? zc5B)k6QLto9M_6Y>U?(xb*!k8zkBrF)k*WUlLSED=Ok)4*6 z<)$c?sKc%6g>Hxa{rdR!{QB@GbEd?%Fn)>gxjS`15Vu=@`lSUfS+-T>Z;jYfUVph> z@3b>mYe(Mk;BWoMb*J;KjyZV5L81S)#I3~(>WZcX=P1<8*qqm8actG9cQPX1)qjf$ zU9y+Vc*`-T{m6F>px*_^WDth;lb_qfU!^shcMNB4f9%a2CAeJUnLE9YIT{}AP7 zxWR+#_WYxDPwqxOTPAew)RENvakDn`#PJ8tsh)LR@!jDYQ^l@MJQH^0gL9$9=?|~V znxgO9+wEyq{`vN@&>a<}stNoXGL0%HWL^$_tEf3oa7E%yUd{7CzNU?8R~Bw4Kgbe$ zWYc1mm9t9hgxi^!JrrQlV)>#oYT^8ot_-ulx~}bTj^MS9D483k@Kq!Hq2qLu-M#u%OMUV;y#BpO za8ur~4Sw5~m%N?S+G*>w{F;58$=vJxvxJmHE+zp>-RYCR@~>HX{Z)djX70usVYS0{65>Z++CRMf_si$g z{PFkyZ6wugS?ixfZC~C^99|_x}R!fSK-&DzgmsEmh~Veabpl+1XboYUb}R_sb=tOZiBe9EiM95H*X3pX$IJcY!&4O9L{=z-Xy#vd95ZvLf^contU}hc z^8A03x_8#^`IWizU5Vylu@`HfT>lVgI8Q}W-FK11}t^_-S zcC5fu-IcG}>uKp3Fy60w~yz*VKO&h|zJDHyU?Cs(**2!D9`iE}7l*KFVv0YyK zc#Wg6wsV`fmD{3tp6`n^7HMQ`I-=-x&`47;Zljl~llkL=$Lc);ZWt{*Q8Q8ha^j|X z{#NhRf7nvCJe+sxPuCKG$?=AD^S##ET$w!k(*8}4fB*RUUOQI$cwnc_VWT6z?>wG6 z`Dn|j!s!Xp*Up7ZTAO8f^heUgEY_Hlu3p>`vlz=2jbGk)?{QVnF3pieCB60I(&Otb z+}yV&Otg-hXzg@k#s80)f%Wr@`%Ws(SSO(VqM7Z)q5ThERDI)dd)uRKdhyBpbKALg z+^BJ3nWUcU)ci9zA%wMwLNB%5l)&Z)Cu23tQyPT~$|sJyJrE7#}a zP;;c{neE2IXV!lY*4)!%^5O%>-ZjqrlX%@f-slo?{CZ@j?sPpAXwo{Z4y#7PwhxP5X7v z*Rb#N>H4^M$7 z-P@IFo0s~WES{~?zx?B~)=aZEp+{yv_wSd#9`)>gXhZVz8d3Hf{iAQ37Cqc{Ga~J4 z$iB@TxAV8G`V;@xV*RxG>)S#@=LIjTUHLCOq$gVR&RVTw(|6`D%GOtZmyf@=y)NYc zRN2hrb?c5fZ{NbdtM#X#e#F7eZBGw*^_uEP4i-pl6JeoU?3 zu*gPNVl$>u;=-5r36xyl_p}*_1fTtn)8-Ok~`3 z>`BMAqd$LTKIZ;quD$NvTl@0R@WZj5XXR=$S1qY8(trk~&L9wQ>Of_u@&b*8hX+lbbj>s%(!(%S5>gkyQu zb7oHcw{EXMF)4y%(Qs+V;`3 z`*i}_w|!-I0g#hwgDC4RqM{WL;f_y6av!1o6x&h5!Cy^}MqXN|}5UAng}|2Ch$|DC}b z3$Fhv7U3%%%dA+X_F0Bg(ejMZd| zR2XXWtKpK`#KQq|dnYB{<8XKyk)jfBmZYs&pYA$~P4tM=q(0*bv2!LZJ$?3csFIsy zk6^*OAJwaVUi@{#)mQOOrU1XhA|0!BUB@|u1;5WU@OO{$6f`e-ueLK%XoeBPj4w+| z(glACSl4&i*x6q4KWBI|U9~@QN8OnwmL>1`h+VsP-!-t>8hwZx9^m#2qW_|A}?(7Ltd&O5b7ykFM z`7A0it+26dvE^g4iSt&3Z7*1Lz5CO%x0j!9f4|-P(S8M!E$>^7U48LZeWScetf?ZMF#SdX5Y$#VMLI@ztB(>m{V-w~cyv!r{jruT-pCsE5g>oiMM>-V`8 zw1=!ZxcpoKv6c&={fe-7zZdgzyxr11yKN1(n|{ zTHl)!G&Aqm#C0FuUwCu#is2QxV86>*4vlN-ANsV2-hS9KwO6m}RgCY_KAL<= znpCMd`9Iqh+nA%;%kQsv`*zmX{Y%Zg_VoMgxMnQADtiAVZ+rVa)xUO`eW}pPIN99o zD&cwQWFvDZHy5OEqm8&#rZ?*&&x;bCX zO1&8Jyh`-qp7o#Cz4~=KYmEWh3v;%sO+4Sjf6$o+#fBgtnbSuDBbVzUs`XHb9}>*)+dRZD{e?c zd|FgGGcfE#>LPES){8TJCU1;NSiJoEjo(S?Z~EAFt-IK8*oZa6=fd|lo1PayWv%N3877Q8<<=kil++4SXqcNX;Dtl&&MlX7oLdUE-f3Da^yrajqf zGqWP|(dF)00g3z)n-!Yd-qcGTV0of6OC@acrst+w1*f~ZXKO}3P!uGfC%1UM zien4&PE=ywp}jDy{qdQFybD|9nVoWy%v?Ct*%D373-LvY8rxSO9DyOkD7Bz#cjGfc~oYx(aiQWGR?-H|K0NBKsdi|aYL z6;-^MPnmCO-;8Er4?Z>O*w-w-%(IrOjzMXU+P$(hwomH+HCpgiuyAZWdt*0SW7~%0b&J{p1@bMV zL#C~A==X>0q zdaHa4a;$&aAZ}QoF^NU6wm(j1)pE5@NfVFT2e9zhyxgKPd0xcB>%LO&Le?n#y(79H z@R8)==>l)AwsbGrIz#6Cw1?dV&rarD2rhUKHS=KM8#`k+rK{R}??aBC&%b9^|KrPt zRLjQ6C)iwWIxP3Pcxc&!>?hOOCtEoh9d$5DzIZU?#1F%8dO(y3Z$+R%s8_1@#!OLbqe~vrPLI@=v?xZ#kg!HD}WPgp1-gg&*0@)_rTD7t``XibwH@TI@7ymv1}H zrJVTO;BR@r(DQ%n8<{eNW2;4v3P=>l&gWU=5aFVF;KT&klLk|(KWQ_%9y6%lxY*&cvTb)R=V3m%okJC+<4uNmplWd6Pi;wx+6- zV1Zta&icu#`W8Gf43DfnYu4#FNw;_Tl?4~~OrG)j$+884(s_P&j}@CJKg*5&@%wi9 z>77*$pG{I?4|+^yeYoz5r6ZsJ2GOqcMfFYVE_XNA&S_!uXlmG-ZNsy=$i%9*OzB;J zj{D7XX$cx#ze)@_Maq2H9)xfyO`JVJrmXqP(#n>;H;udcQi`p-cXOsZY}x);>SjS_ zxK4}Ws({&_?E7wa^Lx)QV+-{$oO{6hww;+G_rz^ZT&jv*Aw6m5tMrD;ca7`&6!QsM+GKBmQH}#y@V;jF(I6T>5aS`@pXlqq$dk zS4pQgdd<$a-@NuV|M}Gs8C6HQWov}ar_6aN8W=O_QT>x?4Yr+uD-J#iTqw}*@wmuG z=(o?V8kwWV)$e>^)vTXB?UZ#+T`*6@?4u3aFAK3;f45}XbJ4F?PXwI%v7_&X+^yT|A6%n$Zrz$Rb@aEzPgSyW;Dxzfu4i(pCe|3@yp0T3Wm9J83_x8Q@ ze+pX}cP?g)(pyz@w|@U?$B)?Xok_lR`tfvqe($S= z3m=KwL`^LIo&E9X{pRNF-}h8j{QvPYbt}`wD^q{^9-iB{sbS5};?189U;qAIK3?wr z-{92v<6+5G%vT%L_xL33dT_xZMEz=saZ}Lxsh>A4@Qy3qAowA;ZKBI>w))M?#y5WK z{ugCv=H_rLHBs60!iDL}igsM7ta+jO{fWkbj7#q$rZ*j&{&vlw2-(i7a^Ix$C2cN# zsucSe{(9FJ#^VQ4qdcxXcX`Xnyg0?L{ny-$pZD&0Z)g7}*SAy5pG)_{Hqo^wj8^Wb z+)yMat@|b3N?Jtw};&T4g=Q_iR z*L88&ofezua$alYWqV6|>k~KYcbyiHDm`_>)j|C%|N1@Exn)PsdVjscs@SBHoZQar zIL+N~?UW18luP=HHkI!!Kj(69?#sDGS~vHGiO;vQ-!D5^`>)dEC92uZ4=awTKh87} z2`=7R|95Bn%g>LOfBzqmx%j z|7}<}#rvI&@{`AvTQmQEeR=os=d=m7-Kwp2EYpnRR-Oo`fB$Lz)p_x9^TnSzpU`3X zBUAx>Q**=^kk9HxyEO^B7dDZ9(UrE^Q7cyU+GVk+ac7 zS;&UJg^Hk|b;IVIZpN_9~W>x^wP zc>XS%-#xFraUEll(#a<=B471p^7<}+RKKH1pJkcug>~z*lcJ|Tuj95-h`q12qH0?1 zQSM@W9VylIt&HD}y!3pQBO zv-PVP@ACF;Q#om?^6TZ2po<#SoB#fEFmhf#*{(+Pb##2H`YTVHt10o`W1g`%vBINTXJMbg$t}}uR6XaLtWLQ3>6vX#zkJ?3*QJ>|#+TAec_$#gQn=SJf+sgXp1@-pL`y6-FHs9Ir_{@C6iD@^@ zPyCf``NzvvqI$rb`|K%B?WFUe26d~V4y}q3VA-tmZBdkh;sz`E133czCiD9Be}(D3 zZ8^I|a<0PJtxu<5b|}|-mBe{EDMY_ z3KiZqP&QrNa^URAD~Ber=GNZ&TUGi$?Vg0D7l)d+>DLK8)=Qjq>b3@HO??v}&Y3Fb zknEcG>dwxPGCP}VmCtqN)#cY1Y?vkHb0zV%n2K15+R-21uYJ$Ya;$HCGxwapwVSu@ zKiw^TIU@bb4_4tlUC*W%c;#(9b^4t7@f8mDc^VI1S)8wSC`@vSll&BwnVV#SuV$S1 zxaF?d$ER;U8-3|C{5A9Q<|!8apHy zZt(&E4lGSGxV18c)tEjfCH1p}1=mli(otg*y2C3k`QbxgoRUsLQ=qWP(nlLNPnvN; zhv!4^Mvv>vEjI#KQYQSHal%Tn%B3e^DO>E5tgM7tbxkL<4JO{{jFiruc;)8bg}=A{ z`SaN8o$`#6mz!_iF}!zr(e^#+ZP%O;n2-R8S0mw#iz zjWdrlPQU)RZomDGQhRah6)#fV{u$JK-hS`DROQqCmI)uL18zUf>+;gst@`K3k5Aj5 zpU>{{jJlk%@$`yM8+g)OH9i|1xTU0Udye#!-%O{P>oe|dR=U9>-Q@f0VLR(mb*?Kq zM=tG2?3*$#LO0pH)|dOAnn>Ai&Hw+t{r!BsTzmWS$?wd1`DGY(c5ZDDc~|dwp4rRf zjdLYu>XF=)bARuXm?g1gSNP+tA0LHyE@=#rGD>x~FI=nfsIAzQ>)Q;+%89=wtZbj! zd2us`lzL}}T99`AtQDz68b{VCtZ|ib*zlL#x#8D^`}%=yN;|fc=AFw^%juUCIV~+O zH7WFTNThgRP*u`Dmc&nYa;Igme42D@!PGU6J5D~)zbDhQCt&}+<7Y#Jlb2>qGV&#e0X4chX#-@ZA| zf0pdOnr*6ItgfDMn>T;skBJK(DD3x~xaUgtiB)eGZFN^l(35->@`}}UQqZ)Jo4T5Y z=hkr~-C*DNT_fiFmB-01oaTFa9bCq;j7?zY_nej5k6eX2&ZeC6ds-GV-GIZO%W;Cz zmxY%X=iI+@SWw7+l^K`>jk*&)p5BKDV^67KFS`wvjxd+T`hXj5~ajdz_?!nX$ zDtjqvlfV}Hr?tlG?CNW(B5(F>G_-5{dQdEIxuN-@x?&^O-CHLs-f%mh{Oz*v<1W?} zA)BAgX55k_wY6Dt>)xJQdFh|R&Xpy{y%5?fcBB5;LXFn@pEZw6{<|+=t!Uu$1AB$) zTz$BU-KVH5*I#CPaB|XQ$@Q3%;Vy+~I~MEw*>U5J*wfFC)4p!& zT`Sa6Sv#e-qIRuharrvlu3I;&_ub#C{?7LPu_be}nIG$x$?c#0`|g?D52t#6%;}gv zCxMSAB6QZbGdt=t)BYGKY){wOea^F6*JXyn@6|b6k{Z zont3I@A$OuhcD~*zs^v6B`21Yf81BJ)X$jJ>i9wi_r2R!Tt1ky>2cbegAtGCy6ov? zR*+OaUV8Y#S1G~MPhLnDG$gWy?Z3R5Z~OL1R&7OG8=fCLFLy2|L9YI}p2auEhnIX_ zlqgKgzA&k!yGiWGfi)^3HhjAl1?-dRviO$a%20V}YT7M{h2GWb(K8;dUnIkDwXbL{ zysw$RCfvbV5Fw7J;&?O)Lpv*(^@l@PtiHF(yh8> z(j(tf$4adVI4`aKtMtR#Ek_{DO_l%Lq5gw*87B%}*hYOZ6DUfF%~IE4o+i$JW$j6?Kt^jP`SK0z9rYJvD_F&PzOktFhrGNNc&mO( z$=XSK_DadRIKGJ3Snl(FZ$yLD>cgFkOKwiN5wm_mPF-^&&yKT^o_CK(6m2-ZAZWvc z(7y@aICfs2zkNec?-hBdT&(7te5GTcCYxul|Qi+Y(q$FPCVltTT7tfAdddi-hYE`?ZntYA>tQ z9M+mWCx7N?rutx|%bztTozY!1zj#Ad#(W+h7mJ38p1b4JiVi&r^Kjg{=GUhXEhiW6 z33u!FOe>ILske|3O~0U`CCg&@)^^tfd3-XqsPMZJ9+6w6p< zkf3+)lCRSN7k~F%7mrf49kpGsExbAHyX@*0C$=>v<-C&Vjk`E^6|t3!f! zQ%>B{_2od`c64N z>x=pSKV4x;WZ@Urt!6v%d_PnD$1hJ`{w%Uw_G#Gh4)uoGtho!l$Ne zk*9F{>(7k^4-V|&yDhLo-zI05yWCMmq3(>O{FV|&_RQo{T;HI|k{DFZb;kJ3R`m;A zJ*JPt_cc^=mL-*Ei3j@%vuTv8u6vl}rLi=5* zF2ioKi*b+VRGd`{VJs5i2G$h4%S8z%7>~R-63(J{x~Zaa&O+PM&$EA&9V@qZ zVQ$m*U&UEb-S6>Uy;j1O%7 zQXQdsv_3~=r}h0WX0C4SwtMVaE|^W7n7gSrdJ~IeNw~Y~(tXvM6TO<1R;JpB{&U-A zC89lhdrIP`A94OCjbfDdMD2;?Ke~V0jO*X-uFYAvYJ$R-(!RUbDu znI=*BaE?aSXU*lo-_AB{P-(uQ`D;V8ce7`ZK=qvK^Q5-d7arcxyZV@Hnf^`v$H$*f z?|q~Eee=yDdmSgAPkk9;)4yErtQULz+RBW_Z>1J1r#M)r$GY~gG7ARqM&^9C@i@}*QT$Pq zgueFTOEO}wtxg`?zD3(F=E(5}zeWGf6l&Z5>B{#jPuNbh-)iBLK7Oola(ue!!cy&1 zjUI74Q|+Ynf@fD`*k`l8id&zPAu_?tIV2{f{L7cdPG079x^G;SEz_hD>u31=Y}DXA zp0t8*Zgtte@VbTWE$x5*%(k9yQ&V6zBWiCzVoKdQhM)sa6^gmdrfKT^Qr*j`@@_|Y z8E^T&Efc?6?0NrkrM>;0{~zrQ-!Ex7ede$0`=>jsl}pXfb+c;j&B^oNWjUK7MI#RzqurQ>yb#krLU!)>VAJzup{*H{xzFxYbt*3`V>*y~3x zW>M|5oXpM{hMfkSt$U2mG_dihJy+?uYM)wZ;v&v z=iAxZt>4pHcskOe!!x6_=V9aODrZgVr&_+9veWPTmFStB`5T;$ zM=#6_R9O3k_fp5P@>%iJ48{{8sz;pf@*<5O49d}EmG%+uwR`;4tnEzqOErblQ; z$?qe_%UAn(@x_GHymhMIDD$m!#+N7Oq(xl5JXx#L-(5WSxa-k*RDnic&VBz~(cmDKwyCt8*X%CSmjTY z_V2OTv&QCN@8Zm4pF-YP$>0_9G>n8D%DKIp@i82GN1bf@01y+wsp_<2lc*zD?oMJPV2K61@?b-24^twHul4T}w6PG^}59 zYRAWOcXrR*^gQyO`kv1o=LAw!BfsrXk6%%|{62rP%bnzH5B8;mc;EK_vVChT$GI7c zH{?yc5G&c3>1We*>4+us;Y#64Gneqrw2o!Con-gzH)m4Yao%dNb4xbJdW0XHEVQ;E zrP-qXZOI}1-ZY+2PxYpEJaKOmi}Sv#CF*M}oYaynx17nEZR6)WUtxxroC_SPqW@-# zxTqhJ+_}Z^&SF{bihAqL6&aeJ&#e)bw43kv<;mPze?Pr^c)3W`YyC~mT?X@JS50f; z$o@NJ>#B$|76E=t8SxTdIKDMB8EPwUIwSh~Yy}(Ns`{PspUPSKzem5}v(CPLU+=ll zX5F(#^Ro5i#A}~N+nGK6`|)iUhqS?#$GV>LbcEtA%1nK+Y(e5$!Dk01tYTAf?VfgI zTFaLuXQK_~d%iCUJCXqdh|MRMOlf-8|IJo-cI^OPIOL%5) zRw?WgIwn{Y&X^cAt%!>!W?IxFg^*>e2CCP!juvq|a?jm=UaPr$;%I$X)1M9Hx2k=v8hF3^^1@tSd);4F<#h_Vb*diX z;Yn4mKdT5z9N)5(L(Eg!;k@wrMFj%Yf%}Ae4;aO;i0d74J>uSU_UxaPedjWHH-6GO z^>Uuo;lNh+%ehQp6@RsoQg5uDYrFmNjv8y-sUotXULEyPK2cI99xc?*5-Uw%oY!Mq zUmClu)q5f5@(angi|Z%Zcsx0F@=}Sh)BLJ55#FUgbJnSSJ*jQOWnFY+n*_tl&C}f; z%+vaqeTGYZ{(akj=VzU|x$$v8$DNJ$E!IuFu~lZJH{*V8iOa{>dQx>XuL`6DFFDC@ zTXS2+zRrj(NmoqOA2*tJ$;}avc(eXQv-kIX{3-19hZ!_3Ca+2jcb--G;O?d^sk2oZ zSL{-fd31y27k-p^~}r8-_H5f+w{5gTAU&eOX8zw$@rpxv}Gn1>M2(0 zbM%@;cNS`$T#-~er)O))!rYEargq)({MtDYJp83fo$anY{pBKW&n>!TZQ$12BAlL` z**B*-g_mW+nprM=%OfvGE@BRSqi{BT*Nw$%KPr|qR!=T>i(FH0+O_AJiCvyN?}n!8 zqX8nOd3WdMYWE(Ww8-I4-5Y5pwT;JD2*)1bJNfFdle+cGGA+-l>c{h@n{F!FET_JT zu~jFfJ0hRw&?K9g6E=H^Z;Dm>`6nxUYxkW%*N;z`H`t$>yiZ<@f3?VJRh|W{J;sxr z9ykSX%jjNzvsUH1m&m%#mG$#wJKT73Qf+;=raZJcIWzZ_o!Yv^DwTVJ?a$l|3;0nQ zV8OFIESI%*{-4FIt}R!*pL7I#UDh9RTX$_X+lLhI%Q7n!T6N#1eYJi)OJ^C6(bi{o zUeB%RdtrXC$zsjAiFTe37k9jvtlnK48MyQL683`7BQ~O!W{OvHUiSH<8Syrxevv41 z^qCtq+myeZc9Tn%d3$l{%bPNK7q0xA8`%G)re&>hbX}+H_ga-)$H`q%-;-U z=0DRm?O&oF|-PBoG%Hz!YMCn*#^J}S^XA(=FOv|wg zk?BZDj^C3xz2WoIbLD!s51e%<-o^TOf-SrC+9L6zY4X>9-aI{_;{DyurI8B^H?Fri znKSw6_C%-asT&Oi+ao12SGdmJvPsHWaOa#GM~+-5Gunwq~ndYyft z`ti~9%*l+Q^>c4Y?D#vklRxQC!S3tygCoDqdx^X zuRKaLT6xjs#=gjTnjv}9t@-o!8ok;Vk#N6;`L$+gz_d^UzV6gOJDWtoRlH>hD`p4@ z+++}peG}h!)HleyHMU4H&+qs(r@UF#cd!04*Ln2*gF@H$O`i2aTg3Los#kyZ+%2r; zyZO2N-?#p+leUH~*?a72<=gE~pQoRcym}$$`~9*Xrqz~rm+89iYk2XCF;wKg%a2D& z;`{G0`KKy9FIc{*qW;Fi1NT_^&q*)Xw8D_3Iml^dWQ^H%)d!XWAAJ1Y7WVxw(~QeD zR%7|keogHx=ZQ~SB^Gb2SFKO4`#jb4-27iZ#B=}5KC!>GN+YIHb~f+Yvu$DJ>b=d@BEN`_S^YadiU3@zHW86RJg+K zOWWp^7G|5?zfcL6PT666H+sh3)z&_DUK@xlm0M_bcXq}5bN{<|{#HLL>uq>CYnj;G zs*ji7%NIW0Uo-v2R7UxL)w6tly;JmGMu)7tIOrF=2~@!UA0r& zm*vOHYbO7i-Io4wH$6UgZvT}_TdZ{1a~EBbzxDsl-K53|`yx-}Z@*pexXoO3+I076 zjAr%wcWF-m4be&2n{ANf76`pSmdcN@OnF?)OPTlIrQx8q}XMC#o&*PZ^goM*@7Z_lC^zn9-M z^%l>?(%%vLe@8T3zEppCLfrm(kNveb{y!4?yisi^4&7eWF~3xJ?VWQgzw7PgT~Ok{-Md^hM&$gz^s37tz3U}P_AU1OBWWf- zd0wFNguGLtn~vWz$ji{blD%&Ewm)_|9!9LuJtwm8=L!z-ynEY@%Eo^`{d{?Ssfv7L z@w6m44(XT|)jW%iFg@SCn(3B~!o@4O{pzdEtWP+bdeNJ8{mJl?dnc}36UTd3T7OXl z6X)d!&m(tu%)M&%glkOeDbMBl{$~T1_fB!cZR!pCL>~UDn(%Ew!Y!w130VxPY;taj zKDHA}S|biG5S6+)K`U_alua$$L}xO+WUprsI6QI3!S1EI1g~CW_$%D9DCpOjj|N8# z(=G2zdHVMBVgJ<)-b(d{S5A7#({aaX0jEWAO(M65=1k$EA4J=~%kRFfy=uwaxcU!) zhV5&QM@~3a@p04U)Q?RU*xU5XGb(!auk)JxLSmucyE6`(3Xhk)zZO~Z{o~K+-}&SB z)ztiYnpv;9BSf+`D5;&lYVifVuHpq@ZiSPjI@ZtqeQUkY@s}RT>n5D^;>@@c-D6l& zlcbh0S^t!6gqhbgwzHjzUz9FzEZXhM;kAOrQT>qxyJy)QhPi!Hn0@*VFWSm;PRIAp z*?CuE1n>Lt6ds7~I4RrZSKY00cn!y$RK__GIq9N5l=8dl8x>zLwLUdkqG7pXR*@z28}uY}sdjOK5iCqvP`P@7d`c-4$!w-I8?Y5L4m|kF#ZbN(>)dWUKB+ z3SBl$IP&=WhxE2fOJq%+eZKtr>zu}UmrlNRO`XLpTq#<)iObsY%Z&^A@9V$6)@KQt z_DRsiPq#!_>l*ijz3*Jw?&NDL%w{Y*kSzR@|J?hJ`;AisC04U>9blVu<3NFi3xklo zUnkpnyY3w(&)Bj~UrI{Ya(Ct{riPEjQnEo45K<@Oq})g0wfOv~E} zugNVx82R$jqBY5}60?MpU(S437s9)!euawSV-KrBzWJ9@13t4E^EphKay=!wY)L?w z?a~I0B)8Koa%*`$dq28YC^o4_!}Wu2Pvj+^$_YLy=XvJ19G-D~V-(-z)8$d;W=}uP zKVQy1UsEMw@9eqO5j#Ed%W|$fKhRQ}aV+ve&!!~Ld#V?gd<|Ue7332)F(To`Gcl(8 z-5n}jA3|LB?MOM|^YGR7GS+{4I;^+Lu=}yFURBoQn4ngD^jI(NlJn61R5LY@RPA@!FU7jIz>QcT)rTs|QNv@%ogD${h`#5W(WKd&2#!nc|h~ z=eOV9J?rE>>vfq*CuY4Declw3tl@L6{L;cTHMVM2Zhtk+XPm1pGl=;1XGh8D2~7JB zp6h<0nq6?OoYS~IyPzz8XK16;oaHi;`|GbgsM*4ne)UQI`>!g6VN0uyaIIYBDr5c4 zw61gU-LvbPzxw~r$g2LP+a4_(aQict+?Q+L_H5s_Jp0PGlJ&RdNlm>qPo44ejW;n{ z%9g86i51R!|5R+L{pIhgKGo>2{Gqyb_D+}PBS!nhoYwaRZ-{uR+AP)(@?%eG?vB*8 zk>_6d-Kc-@x&8QjxoOckYmFR(1sp29-#P^H8rYc^Z{qDqI%W1T%*|YtP3GeU=bZj) z9gJe4Pc)de&c7KfVC&kQ+a9w^!g93ZMI-iFI<`wxLP#HXwqT9 zm!g|zRPT{2I_LYg)>rHJ4#sYYCG6+44n`-`9tc^X;xxHlhbhkRXXGOj(LfH#8V#;D zeq78vVg_2b#NWjT1f@K@e&tkmk950}xVe7l`6&w~#U-2ey=YpzwE3&3>o;#FC&M1m zB}cwL(Y{x6s=xoeo&Dd^r5p3Um_*u0-T4)=_U(pemKBdTZd}lqq!e~%siDk-OyQ+! z4&-RW^ri;yd>P=A!*V6aW%@Re(<@YFP0ckiPP$t(eJ)e8#}97t?LXevr^Puwwn*ac zR+YQHR`jib=TFIyBSGd;7u1xusW)B{cu?hN@+MaFwaAK-Tr%;G!!wiw6OOD}E5GsG zp3~orT6muNX~j=*xDd#(JJ~XG)8)r=H~3xpG3n&3^B>iX11cVrO`N&FjWd&B1MlaW z8e_XoJ+m&g^Nv&9Q$1Wrx!1CMv@k&E7$Bz^qXVV+YLcQ`#=b@N)J*77^f$L;2%RmzsE6m-W7$T=G)jsz&qAjqC@GJ<8a!a@P^bw?0#!w@*4gV{2GM z#|E22T%S%)-SDUBJZn5?7yH+qwCb z*5`_CM3Z#%M84hCdARmOu<4xTt1Qp0;-0#F-Mj1G*=OFm_rq;-zS+|cTdRKl%1o{M z`Tpmp{kNtEEn&P~Z!hh!Z}a;;ZoN;bJ2!_o)+*1;vsK?Ew%+FWUTdKx$8*yc-%(lN zuv&WUGbi;wQ?jm4J#YPe_Q8GHyK@yPw=EXSGdQ-x>*oQ7?5Qgb&La1 zj~2X0^DJ#rNq!#sUOql-PUdf~Cza;)Ir7)Hy%*Bmemw3@Sh^$6s@v8aA8$T;JXQPk z(ziA{-^JYfHt%)ZP64x)xxa3t8lJG;8W_J@ptMmpZ+Euvt&*CvZ`IeH+3hIuHm>J= zY>!))cc`<%O2LFn<@XADuG})c_$(^_<=m_zS(2-!PIg;0&3s9X$QRYi)kk~3Yxll9 zdw6&Ke!H5Q-BJ>^3zspUIe0IA@BRk|rivv8Y%Tg7ow?rVDRBG)iASwM1gyp;^^EYvrs(*0Hnkh0HPvXmYCOGb~kmy!+ds#CuVlo5PBJ zpUth<(Cyi6D)9dCYPpv#&v~=FW;onQ(C7Ltg{jP6JqCu6L<}5iF{BgNVOi%R82?n=3TJjb>o44}k z9P5L7ZiHLTFTAyGk;Ky5XS>5q{3w%u@5wd$;(VVT8^48tH;V&E+$4cZpqG%N1rL*5wywCg3uoNB*ysUasaZ zhBrF;+|OdyEX}UI!L09Q(!F}!mKk4u*K;%rJm0r7{lc;(d)nt1Ts_FfAQEk66RL9| zuoc|BViek)&J=9_af$Bbpai`Nt$D|YW)%k^h$fBEIko}TlD z>o)v7m=d^TV$w1HxwEXdH5tx({U}xSuJ_evaxl=Je|4h>jEn3l^+``ZOENje{3ylM9kMe z){73?nhI=tRy-}86gKVIO^%C*Qb zD}2N0H%ikOChWPjv8I0hTQAG0!fWgv1RUkl5;)6l&;7dYPw|z{Tnjh0>K%2sA@#0m ztLUGvA3vYId^=TI!J*wZ_FJXEHZRdD+D{ulTx4p#-V-TwpgnD$hp^s-=92Qb`Ft{2UM$6=&G2vPje46q{00&M z)qg^M%-;M@sg1qf_Igf+^OXA<0x}1tKM|U_!hg|$683*j4#l&Id@tDhnD+&HRqmu^ zS;g$#(Uxk#0kRARs#aV_I~?w;DA8GZ?_q=Lqx%viH8C%>)ftvDeqk?R`qi2mHNz!t zxeJfGs?!E#t;F?b!le)1pLefU`&WOx{oeTga+Qtl^I3U#&Pof+V!Z6t7}=!kv^ITx zC3kmZO=MPYfReh;VhOI=4{h(St_V=kS@67IdhxTv8~xj5oD!Go#dJ;0T#;fdzG~B* z=

|%oyT(EAg7Hn^?B5r7xGW}I{d8%kLT>%4$8Y_=x_*Cn*XT>n8vUJf-rp*(c~_%# zq2^0;d^G>f57wJF6QsLUiqzu_Y&ErZ*Ti4WV~n5Hyh>IjQ_*#8)&B&y^iRc8<7e9c zf5x(>{)hA*{yJCly&o=?|BB9B5|(1-zhK1)igldHb&iL_B97F4`Sb11g+UUW&r=j}06*U6d7H3Gun(ca``L|SkNBjkox!*zUtg z{&da}Yt#r5U))|Z4Y5xmEloUyd*(seau^J($&lU47!{%5|k^{c{%vNqvK zTpZ!o6s0Ox*f82?{BT!if4SS>&c91nuX@~Ff5&a@#i!Q$#9OV7tgiU+jXnI^@AdcY zU2kXE*81*)(X3UDvuiI+{9o%EefxLv)~6*GH5{6bX4PNkTXVPk|AXA0YxDLM)!WuB zp8vnt`d@LL`?;&Vw?BT5$(gXZdFsa_k$THN)t-%vwtQ`Vcl|E?{{4^aV(u-we|xKT znn@pDV3YDjg;(z2DvXb1PTh+*SJKU!QcE0{482*UZ~|f1YDoE4OF=H13^Nv-|fmF(edf z)z{yTt6CoRq{l7S`_dJ@fNYoL3I?8X>le?Nn3{KeuTtukU5cJ9e|ed2N;Tx!ax2`O z`8#s`@7K@kTc1P-9nhK?vfu&Fmrdr5IZG76nADzL-Kdbz;lG{Z+4}kGUBj=;y>RJg z!8H5&*V*YSH$6W4t@r%h2gm9~OAGgkzHqD++qc7J^1dnWGjH(jt5Fg#UM)MhW9t3g zKmWhjyJ1gg-1{f5n^uQc{j@JXV*j%5h4I&}E3e9z|#+xwh_V zYC-MNKXMg@_b+eOkC)rOM7K1Cwz{(w%7N{F!KJHa?#e7cTMuXA3sGcQ@H2unaXYTQ$S>TYRQE} zo#_fCpA>yAoMgWH@2s!N#RbiIM{Q!gK?KNV*b zFa*q>HbKu~TY{zS_Sy3oj|pw8{AGRjWaFJq;ch3sWrY(0^l}`Hysq3m<@-_8Os2m+ zdR_k(*A(3aABD{JFSot=v$nV?>|49nbe>m|rw`t<=-YkfjAP-;)SG+{wy$hU)OLBb zpmASMT6Fz_&1E(6N>b~uFTST&HRDU(#nplNzXG41dH-nvPsuvXp3lLn%1$-jZuet0 zVOioFsCMpr#2=0GGo5%mkIl+|_T8yp`L}nAtLq|lo{fL(8}{s5e0z=ig4ZkT4>CPc zP?Bi0d|SO2Sm3Rc6L&pD&*=#sN;v;0)8}!U>wYMP; zTbw>Sv+d0`lDopbp6#)IKEvEEds?nU?|8SfHU0k8&#mzb9=ixu7|aoR%VHd}bCT=V zH7(N>W8U(pZ=SDZJjHkaVmS?g-X)q+tg#=tC-x@3E!nUkL7|7@-?AlM)eA7c%T!wY(MHCUfAYJjta54l>g2@uPXF7Xu|*?z{XD<@6T+9I+TZ*C z<9lndV$+#3`c_5)r*HSG-ZnD6ucf*A^u7zv?yY<%C4JciIJw`X=m#T{g5+xJ@X z?2IsjFF%)`<*EFZEEp6#j?bLRDq9i|!FXP# zCAiV_V&k>R^A3G3S#q{`>cvIn$BSE%6FcLS+aKMIx4XYT_Laz?eH@hn>>-Ue3mcBh zI0u&0Gs(6eQPlL{(|Iu2)$+81okHJ-wglCC{*jFq?Bc5aB7KjT^e-(h5-8PZHRLVk zf3C!3_mcn4-(<$UhB2=a_Na?)crji3?mM45pAU=6JnlBOIU`v1x6a~0%dv@^X&GhL zmawM0zZ$q@vKg~LG;{vZ6vMP%j#`;P!d(v>K4`Xy)pw>(dpP?zSLH!YURJAwU)4M6 z16T87I4)6*1cYZh(HTDHzb znssqTU0g|ta8G@2df}rR3Bi(E8|?06oSdzn|6bhh#kHmk-4)5qw|@S9dt}EWp_77( zrZ~HZ$hzlgU*;*v;X8GB>fU$lm+$0n6aKt>$MT?>u7(%N-rujeyM1r8)L$1RA(+PY zd!~royOiQ}QBz_re7mQu$MSY=__O~%47Kk|$n zSanrdfRNZvzXNS__ALOq4U;0a?-!Y$gavL z{BnEh#?225SmOol#U5C@sHxX~kyG9mZg=*9NYmu<4f1=18E!q4G~`sVp6hpl!=>um z{=e0EH9oj$GX+mG3Ai4M6$qr(KYNJ-1aHYNO?bpHNB@PR{F8( ztpyj_$~}Vz1xx) zaWmyt#}ZH7X(&2jScw<36LsrVO%Lkbnl@3gJp#Q6M&%)~}bG2C$9ou%FU(7Rg@`0%z zC;A$@&8iQ4sPceCTTOz~fBW)-3(VS+mN0%aoujnIiYbamY}Pt~Uy9EzUOt`Mne6zW z`N5j0pMGS!2ru2T|5Ep<1+!Zn?sjbUI>E`lZTT|8w)qK7MuHYE<{y2$QXr~fqm_U= zGpjc9bi;44s$HydO*dFQ&c<$yICM2YpJ}c|hfB2P@g$ke_12dT_dJ@(Q@&hs$2Nm0 zqBR#zE-!t~<8S%HP>yBeR7Zot8yr_MJ~EtKc`YUTuz~gQ9a}Ut#Kb?Xc9{I~#j*wF zDdnmz#hJx^+lns<`z;B)sl*@GdPDc@g1!rBM$02Da!$4#xY_8Q$gy!}tK3))_HTiz-^>vbV{b_nb47URNY)h+B1DT_8_aXj}8 z6BKrN@Z<_xrnp#(To0SUK528EyDwKU2F8_rycl4x;KMDhK%Rr<5mPvJ-FtM*a?yK< zj7*7zk&_q6tkR#<5R$X^NSfj@?y^J?2DuH_6v7_08OLQADBU#JSlPpLp#Dbmi_}I* z;Yv?NCeHj<73L=dofqt!Vq+9jYMgUj%shS0^#`1dT2lnr{&LN!YU?)pI$Jp$iwQ%O71@x?2HUtj-kjig zQ>v=YY}+MoAK&=m%E!BN8lOo8Ug52mU2gLE?6iF4IXifR+pQ-(JgvNE|K21~rB^&P zeu{zJWxHDo)X&5>wA~f_VD7f5P2^#Q6+722`FBeN_dB7E7l$LoLT)8+WY{e5-t>*XYkGue zz4I0gfh^{oqOB3q2X~tuP3B!7DA_MM!<|>z!ztuqRm1El67M+=7>By&o7}H{bLo*! zf%@KchmS}*cD-296e%|$$RfnW$o$5vIV>^_J4$+PuT9QXzEJU7de0~4i}}|?wnVH| zV=Mp4R@t(_ciZjocfaDF^_};ea7ggEg-Fb{z{>i&+?t$vsXTE{M0)xH*QnnplT*-| zay;;aqDmq{&rYOcKVb%nB$h_&{zSL@%VUs!QuE*nqvaR>Z4G>SesR;aGdtgId9dwt)9pAr{@2aFpDjPWv$am4 zdHMtKf-@$I8SC$zTq(2qkA?67k(JMuHrZbGpZrJ3_11~yMn{x;JQcMh0{aU(95w}O zoXQM{KP1^}cdpjpaL5sjtHvAVt1)*^V&|@tT#>zEnY4pIFy9*CE0*lnxP5kfp1{DX z@kOBhq%jk3Q~0ZkL>5?}>Sbm=E+c-Su5wUm_yMTQg0YxoOJo z(-JceAF%NFzrN?<>C=Zl$87NqQ_YGz@LxdZIKPe3$NP~UJaX@j+=#N?)@69|g32b1 zguj6ouXg)=D0n*M1ouJDg929<7kYklQ@+0=@!>B&4!h!-|C`Nj#hdQ>^HW-Ooz&ca ze|r1Ed;9ADxh-Gq)^17UG;0@2 z|2;KdSM5-Q;E^`5H$fo>_MEAD;c@(EZN%$^^Ut-1Ki*pVUhV)#o(91j-{yY9p`Imaf;EIPKDXw>ZT|a-nck9s=itlF6 z?Y_U=r*QZG&R>7d<~?0)S^WR~naIEAEVKWwUACsSK7IYG`u4cmnm=1Q=C9#SHNU4{ zcKeFwYq9$UWtnPq*Fnwts5=Z)$LE zPFSUob!t;(qScllW+|_&cdV~eoWC8~TORgo>#=H6IgW3A3-VWVJXp3@@91o{qDO^1 zzqwvqF_oNbwdGm;jtQ(H-_@7DS*KL+|8=-PWbn~nc6)_*|D^TL+h_AnQ(U|`_QJm< z0sT4NJei4UH&6XOXZro?W&QcnB0?4)x+eV8`60h7|6HHuzDH+b4)(I~HcNgl)k;&J zXeW13%%I=lly+C%DRP zvBYH#_bS~c;bpQbPctl*$)6afqa}T|GO70*k7=)bGcFfjmhGI)qbrL>u&$J6&c8o z>$%|rgkvQvM^?Gfu!Yv!;*(0^0@J$b9v z`fEK?_8FWyCG*#4yM$@VIg{^OwYn#~7jwzuDtmov<(Zm2mo&e)X%xKURLf>zEOMzo zT(+3~iG;`W6Q57ocy}+T_RHLQP(Oa!0`=#0eYYl^eE<5n$;^glK^wcd9`8IfQ{3?4 z3isnoiy2*wQZKGA61{)0Mlna=O@@Ya)c!{)<~Nk`C)U_FZ#lNMDc1WU|JLu0jXn~- zjP1e7b4o%gZY*H9XVlYkJCbGV!I+kW3bX15EcGqhgIRsw8}CS6C1$qtqPDV>(~c zYvuK$VkG5Cyw2HYtTo|{ss(<#$Cvsc= zDfw)h((;vO&AyTYk9TSAk?^X&G4px6*=swg6p?k29mkU1pX^k(52@btYuclIv)ls` zb8n^v-}mU6u-eT)@AHj$$tDN>&QKRMs_AL0YRfUpHW5ocaB7)=|H0RPHe6{Co>CUw z_5X@FpG{oiqFXXdhL;mqmUS&X<-&6^ga+;>ZStTP$3Cw(j$n%l`Yn5cjbw*mHGpeZiXpPh_;jjCuB#@$`$Qe(dvL<6=Fkzn1^1*8RM7 zLVqP19Mdiry_;@)W7ZjuDUSjYE(Doc?U=bL@YJ43QAHui+hQ#Agrprpa%lVJT_DsAW0#QGgVOguei1_#_jXRnQI z@;P^=V2|}IN%g!{lanJpMCm?~;kA4@r_=1>tFws)xA-^hI4o+^S`d-O_h~ZInd16l zcB8N7YHa5o-Id%mOMOw*3ATxLqFuT&zL`EPY0bN)*>1NEJ$$LGGB;q}^eQD@h4Y&O zZ5YyZ^{bQa6!Roao1{?h*0Y;UKKyKV16ym_|v_n76zWc=S1>b8JmSCM(r zRxO=HE9U309h6IJFUU`w5r3Xn|4(b3enOle>lauc{A{O8OGAP1Tse=~pMU?a%$Cc~E4jVv&ZUo=E^d6j@q0I~d;LNI{^Wv$ z0&N~1!Oxc~f8S<^a}#m6n|=AwwPi;mC7gUumlPfUx$g0qn70*<8Uhxzn@aAazPw@a zep#};-|@;ezUh^>ebb7qj-N}LFB+GYn|`@qrg+qZuZthp6i>ftbN<7_uaUn$J$(4^ z^CPL(XP5WeWyU>}I#9FzzlDS-qy2_c^}FBf|G)E3kv+TEw2$TX+>DA16YRFmONeDZ z9nq0)yC#)c&pLex^OEx2Zo&a^9Z%0mPkgHRddVlD0GGz9Gky%0f2*al9bY(GSEqRM zc9q=wQ_rL{Co<-5yl^yF<5sFCPvDVPhT4f!teSl6OpC&w?NOQM?w4{jsn=LQM3T{6 zZ+*SQJl}80QOhoPsV8Zr8imXh%o3`dyqPs`?WURcXYhnDnb(W$Gfb+K{4D5uwQ-U> z`|k|J*2L2_tG*m4diL9|Nk&D0^_U4W`+1-H4Hs{&wrEudJtbgavdGcx!VLapI&Eu= z9DVv!x7Hi3?1-cIhpvzcw>;Q~r`|PcI(Wu=MF1{pl>5 z);!p_*;4YPL2O}_$R>+P+vE?6i??lcxz(>Y<8GQ!P#J^wtrex6FVPv=6hnWcMGUbSrg6%t~8Mzzu=K&@%d>f=IdPx@@1-x6J9 zedNlsi|sF#P2qD9ei?M-J?E@Lb1&#{&+Xh+l(2a11HBDf?@o+tEm&}8EAQW>WuHDv z-E~t`zW+gw@ovO1;oEzP0>3)0V{Fosj#cBFxYcM)X6}}lXz7Ue`BR?OUpTe8#;B@L zQ7!lL#jn@T%O=M&MH~@zUDd3j|B7EQQOoZtlX}o5js_vmUsu~dpZmwcrgf~^bL)n4 zuS3n3+gH#3^_D4({a0#Gil<5W{RkGO6UBG2Uy*+QVk_syox8)1=_K71->g6XXNs}G zyFVO@6zaUfIpa0YO=VA_y1darl|_1-TV1*(uZd*d8_8s z-F9dUexmJHzTSuPD#s*er3D{0g{B$u_CL1OOU{@A{a%aiwad;V<5Onh~=AncN1 zL7IlyoSSVC9C1>K+|zg;9oPHo_iKjmw~DK`w*+1C;&-ylJcXlHw?r#HnPSgm)qaOviL$=Ygqtdsp(*BNmM=c{wxt!BJDB{$Ih zWmneT_UDVYJAORKmUTzqc-q87S=VLE>&?4DE6-OtwoRD8oy;d&-?ld5NzSX%4Mt3C z3To#ZE_yAFN}6EB71`_+yRSMV;j+ipfUR3@aNYTkoON>Vh4a67&rF@JSR>*?Xt zHJ7#0Lxftb@|PJcdFA--=7$4~6>$MoBD2_kPPqNFd4HmM=I-r%DT&haR<~Ykn#)|W z@Y`9fY5x~zS{+k!QI4~G9j0H;YGeKKu=dOUY3trhUbUWo|8)8N`(i8ZGq$%m-aQy{ zC$N11$HD_*n^RPFIZr&C+MPB*;E8?re(N?CJ`?Q@PZrzYzrG2Ku3_wAz3X}lWUr#l6$Rk^H{cB1&DWxnU0?b&VZYIooL5Uj8L zrZL^&oy_^lbyqWb}uxHRI2&#-cB3hDXajReTa#up%$_anKi)@Qs+QqtC^2PTIh0uy_9pl$Z z+Kco%-k){)(d!U#A)meN=$G2i1%a>JlZ)-l-V-KfFm~J?_#8b;c zt!%Q)wsM)JgmN96vDxYhksx8;hmz2ET%C+6GS4Nch~Iw`Xv^t}e>UI(j#JOBJT z__R1Y`rF~Z^|#~i)zthb`hUJJLDoRE`GF&&Z}5u0S<2tG7l;V)x4DHHg$OjwWM%v+ zEBN5Xc6s@E&-b;R++bpJXa3?KY3D4-NkKb0DjCc@I#%e%lEr1pzGzQk;N>mc9VzvDFEOigzkmO+;o*{| ztZn)n51PIjOT0Li~lxhVF~`J zyo=WyV@u~3dvzhAr}Y zvU~#B4?5eJyFadF^B;j@F>^`gd#$_oH>$Hq!XwQ53TM#V}bI)@r@5ADHLk|9i zn;r+ID#)B0MO1m^+WpcGWs5Fp2`EXOHRM`=wvI9QaCN!2 zy}@#3iRWfp^PMleI+_0{)4x96KHtP6rrs;I?c%DenX3;7oxW4G`pt%>iVqJzUf!+m zU0?Hlncuy+T~!iH^@POn|&7(O!B7l>QW{%&P_-Ftbvnz#dp zf9;MFuYb3h+fVl0Hc!5N;^~%$y(T8w+CA|*^6*&jg6Z28&en(>xz_mKIba6ot>Wjr z0-EzqZYcfoPu5?7X+4KZuJUDu1D>)inyvS(qaG~cad0|!sv*b?(|L-}H z(<&Z2&2{QDmnuGMba#=!YpYcnkEFi(TFth}x%Kml;_`KM^?PG$=LjBXbSxCUeC>#q z`t)VqGk;9He3bX*-<9XW%v0`MF1PaUyO2`HKSxO6FT-1bGfnfE``fTC5-=*{`(91Hoa6$FGPGhdmyIAD*_>*bZo zmGXyL4sI$=;pCm;%C+7wZod%78kySe{yXSIj*)ZOuh2bL zKez0y{q^PL!?&S1%N`~yJSElm;_eFlpT>GVt(%UtBx)LnhBr6FRqZwT6P0Z@rL>o) z!ere7pKk|t8gJMbly3dg_r?8+13zo-uBS7 z{`BF~rynn$zkiL4cHtb`*xPkMs&cX`b8Y!uH_e>VG`-f}Y;x0f%kNq;3fp#;R9Q$Y zPM<3_XO%qj_4(;WerZJ(F?Noz>?X`Ii&@xNciI2kyWxxH#fozc{oB=lJ^lIb^7Q%B z!tXsPsFysyts*j9AoX%D*IiDt)O*V|+?Z0e_V$8MpWQwhska{nSx+^u)!BHj^4py2 z(?0c|+H}Y^ABUF3i5!&DYA*a#9&fbZ$L7ooUa#_8ex3LK ztIj3_*jnfmKVDT~a#tf-vgBscq%|S(;j8@3SH)|;4*Xwl(EcT#yQ(PSLif90mMYt| zodd$FP1p1_><+x<*03w;gh2agXQ>@KQrG#|tuM--Dx1@Cy2)i7_pCL#8QY!~vx;(u z$BRj&#yrys`yTpk?Iy=#^E3UnJ*`~Q7%6`1lcshC_pbbiBU%NYwWghy)}4E5(WG4~ zmgs6l+Uc)R)yeAYt`Eu#JpHNi!J)6OyY<%T>?%pVxOVE++Q4V8?aojCtK)Owlj8Ox zUyByV*u#6?iM}c_j0*we_brFPnbU z_>4#N{0R@MX0(6h+^Ki-#tO6SD>;Xs|Evs{<}b}Od&rT^+?@84e$72r4{T;RFu zr9DkYFK;L_-rxB0?cdKr_A7Mw-t4jXa5+0Lm&t$a28*qalzwky)7v8N~ zdo5;t*Ym4Y>rb2Ztt%IsqWtCG_R8E4W{yl#A_R%2%YCsL}H=c>he*$i1)Ty}xgJuYO06y>8jpprupx ztt^_Pef-soZ^n2dF6F-(W=`?hP>TJABlBme%$ksCE8x;)Yo(8 zSGynaa$K}(eedg68`kw@?F=khB7g1nqcEw*c_jr~bJ9-Vt~%WQ`Weq_-u-$v*W9g7 z^!t8`!K`Q$A_7v9`A;%NS$(&v zu1`3Sx?@Fxh~zav#eZB(EJl|U4&1jncwg#*`mE#>VV83ZCnS=rm>-LkC+e}gF7~|L z_|Rm{o3DS)%FfVUn|JP2?M}P7^;NU(S`^ZV)ZWQSi>d7l&n)Lpks_T85x9cCQ6)c<(`YX|4z=e*0pwEbMNAKqVHCe(b> zlV{Upg;)K5L>WJoek|81DL-SpxVu%-Oo# z&&$hA+f^R1`plhKpLE`(?N$y`GQGefDc5<;tU2cO7d@vAf9bZa!tLMZF`4Io;)t`U ztya@YJH6Vs_Ve`L&yWB1*WbVFLlbjA`aFu&e~AE_3x`P``Wr6TSS&sMV@G! zGtH%Vw%glPA8syA6<8>%dpG6$0-IkuZC-M_@QB3vhMS$a;&+*~JF4%{x|iNeffMt$ zemnd8_xyZb<11InO`4zoaENHVVDlijQHP=0Rew3>g1kivIsFe#vds3WvcD+Iy=`^0 zH|LtmpPmS@Jy)#qRp8{|{QSvlvUZ?Uy=44UT?^yHkkctk(^pB&G`h%t)#sUew#?k{ zs}}Fi^B!GM{V>DO@QdUPAxFVvGnIK$C1y9Nl<}<*&$z|p?%%4b0ZG@Ob0%GaySIiq9e(*)x_lohXIw6MjvDAgE`h~XDR-vzhE!Y3B@teN$jL6dk zzs_)E@deB*-M!Cb-Ga7%KeDy8UQB+cBiAtV-Oj?I=?~9d{kCq+BOQ~1IUtH3DSe!qxqNhAgIZ!WCpY`%S=AK_K zFLN&5=6EdGeD=4Gucsg1zCZl(vguLLEc1%H4-_e|`g6&jTl%PDuH~iWc~gFKRbIcF z^Iz&uz(X6&dkc;$gjB4ZZl92}{@b1P@-`Lo%!@V5^NSgZjd*wh^6sv#@7-a^*Ra#p zx4n7i{*?>c}nFxKE_pFjhZ&<7H*)ig~SAvM_Iitwi zpXS-#)^RgW)2cB$-M8WPw3Swo+b*p0MYP-INXO{Ck;9#{mIoYjxnrQx%MJ2ZDLvF8&H+cKqM*ohMxq-sNE+?z? znma{JYA4>zoA$+h`zo>W)lwx>_nun2{q(w+fb;L==H0)e?_j*~$;O{TEeb!b9$R~( zM5tbQ)suS{Gxphg-&&f!wbEgNU-{!`d%L}RY-;B)FR^I(T9Uf|!XD!Z0{gv1X0)*% zou%@a{m+Z&gnngb55v~{`OagsMAl}qMA?c;K9NN_as`k`^(Qut8X){6F73^K)^8ve-+PT-cIKQ z%x289e(EQ<;Pu_viQW(6mVch2V#2<7x7Eo9D}vsr+z(u|zi5Hj^5^c10*lX96m58J zKI`|tmp?!5pJ%uCj{fzNmD^-uFFnZCVEJ-n>%tZMQCjBe1~JPzZ>Zm!dof_$vJ$i0 z%ayavzDv#1yX=0Wyq@LZ+vU-|E>F;bMO267f;*U=f{aXhs)AnlB?dkKPjH~%qt`zv#RLyyzv2msMd_4iHbAC&WW1aWQ)&JpmTxl9R zdGpb-Y70AEl^yH(j$hTAQB!9ou{lhy?D%VCE9oPZ_nrSYwdvk@n4;(NkmKsVS$Y#r z2JN_2{<(1$-?vvKYdA$LO6C^DHYgOb-g)pdV< z{yoj4_dEH+`QGGUjFFK9-p*_M%LYtGyE?6(%a$lJ*6v8|B1eS z{r?RyCs*&icq;nM#_N2~eoD1gE)t)rAbs@Yr?~u^r!PNG-7_`(+>D!NVoMWmZ7_JZ zW5cF?wdi+KXU=*v_jHL*dO_-YpRn^akM<=``uFL>pHDx^3a{>~J8?$r#o6v}RSaUy ztKwRw*8iNlZpT;V6srL9U3{abzYwt0)iRYZ(O%r^W#ybm0DwDy@FZbibF>yvFn(WOE28d z#FiV*Q@kvsC3``>xZxI&`Cc1yA57nsc}SA``2(I7=Y^A{3;i@QST60btFe`@k9N7o z_2e1*8i}M?s@z2?AN1vY7iM0F?K6nW>sfa60h?X_)2Z{WEt}(Ff44ZGedDHicW#=` zSna?1!_veBckj-4-ds@y)a-LZ9 z>!8z{=!7M2IQD3l7Kf%_)71=DPgaB*+0$tbt0y8FXt?7<@!rJB4S$8XiW z10k!W&g_5XHqY)v)AVCsK6hpol&SyYpX(^x(Q}{Uy~U0D_cToP~|#r;;N@!30sZ5iY2EDIm)pA z<~nO}X~y{-*=#qbUe$0v;t*keq4ADrcV>~F`=L;cx01e|drP0xIM3+2^p7X%+NXmH z{C*Y4ty%Ect1RZE){AY2)=x8aKK(eIJ&CjT<(snSB?>&d#km$%IabKcTy2t-EMV6v zc6zdDq+tC#-|Ega;d{d0%$t)V#QV4X-M?lLudae*!|+3XoPJft3io^0F7TW_bMY6) z3k6bhR&QN4Njv?;?CtS_XA9K&o?H+NYG7tCIFqp;n&;E9%XVLS>o#0y>AbEXy+(HdeDK)G$ONY4ABq}Sle*sBt*F~!QvcjzL;b7k3K!No-QZzQ z+~uk!soHqp$;39*plr9J=Xa?DZ+Xtf^g^~T+6|0uM1jY!N~>5J-fbw#2k zFaF}ml9%%1+)azd2}`A#b(M5EFYxQ`zOcsAX5N~m$u|wTRw>D-X3o^nn^CVf@zL4x zyjXodHwpeAu$iQ+=v3B{N;>ZPV-5p1>R<&OD;SuQ6?|Kz0`L=!jy?gbQ5jU*T zyNje6^_;(EwbV>-Q2okRIEA-hnY=*=M;Y2h~0N{ zov7$C9f!<(SDu{2!;Cu*e9#xXBGOT>wt%Zpm^XJ$!^1wWq%ZH}-`wbXaD=ZhfpPQW zWA6f0xW9Q6Sm|uMbT$S-uY0&ZcxD#Q=@WaV+`lyWetp-zx;QhLr_UAc zl*(mI{_sEjg3Zi8zXgwFnmj&hyXo!k3A61No0_S8 z_J94)zo(bC>&M^QVc*7D{j|GIa@NY=dmDsq7!)l~-zJ-5Qs!W`FjcKN?~;3gdc3OA zr$ZX$$=5Wk_j3FBPObdaro;2KUEBHZ!>iNUc2@A+k$Bwxtk~tE&lf8u4d&Qw5eYY4 zO6M<_y!p+#ww%I=8H*=3_}&$XrIyLz4c(n9fuxwclRw5Ii24K zFvs=q$jsWb)v)KH$MI#_T^imRv*dD9CK={eu9m2|q102}V^JyGu>NKK7M9;k7am2d zJE>62-jFAhFSFpihYVXB`#*4|IbTVQanQ|f;G4$w0N&yRQbJY zy?=4;_NGf!JF1P=$Vkkt5Gb-#TK(o&g4dS@VO<%H0B^xri(gFqv9$g#(}yxQQKwZ# zd`8Jm$v-4S&E)j%Pd4Cl5ls<4baJVWn)zX|<*LetANX0Gu4~&nm6P>B;c=xO(<2l4 z#H7|Adch>LSZz}6pA%mLYW{wz^L;+|_I ztCZ$nefDyVng49>uTS*OEt7HSsMp&actmyH_K7-;FS7kQ;q$ zp&Z*g6BW2xr$(;nzt8oe-|?BQ#q>)pufqg*xQcuW?DPr034t^AER+n5D=}Tg+1!8x#>~{H|5j zqBo~|tGL=hS6{XZ88=dxi}=(oeGyPU6?xlmj%=&55YJnYo`l6r0&X0=axRQKr@2{+ z7=t|WJ4&Q=Yh9FYsCGxWJxn<@?aBRn%MLB9KfB0MW5Fq&r>eVS0{oarI3|fFS-`=AmI#VZeD~8OE zk$P47D4;R&P#b#=_wIx>Cf)%CI?-7XKi{AEYjI#!7_iTH2 zPWR`c8yz&OyUSA3>OG%KniWzpSw>>M+9U;!w|X)n+cXL#jb=}yfORheth`w>Bq~n{r=q-!n&5; zbN{`d;A!>Aobxx`cg@*&ZBx31$fKi|ek2I0t~n#itFYk3V~ewmk@YhxO%EKIS#qyn z$~NU$pB)A7C|-|V%IM9qt$X@Hqk5;>bzeXJz5IE3szvk>!tDiItq0a7b?dj1oQ=JIo2DztH_*mI#Qo&&eij~eRNqDPe^%H z@$2gp!4K0N-g(dXdNbgh(lXz<4<9a$lB|=f+xg_i-`K5s1|H1Su2yD7d-6jP=BL=z zFBDn+?c%|0duMN3*q=79sc3h0K;EyK2^vaYHXfhKpRV92#rQEhcT&)X04` z+mkUk?xCA`%J$73Av~fEroA$2MDMy=8OvDw?YiEca76QffCf*vt-vp@pPxQ_Zx3$? z+t0cAp|ychocj!ma}j3}&oxMi{rghBw`$(=nho{Q2D|bOa_qL8|3z+TaKTn@-Ev)nPPvbzw*tETcdKC9JQaod)j5=%Rq`}mai>7BN76IR`vHa+#vs}kN9 zFV8VZci*Ynoious^3SGUd%n3vuHJK3r}IbWTsr~NC|xs;gQ_ZTx7h!*oFuZv&p5&~ z#+Ua}@%{s^+xM+HSJ)=OHtUF&a^fNWp9d#@OcJZNzdHT%=WqYs{%$Yl{`}BuvRc&) z-4v7En>~UbW^)}r_3@9L219sjr}Neerk#m70(ONFZxV&M-q%{J>*!KoIm=TWzGB{! zmt4=@E$~R-SbXe3)|Q$iPnN}Z*RaIhvepVdxibE1tz6%97vZ`2it9C}oH6<*qP*(8 z#IrE*7=c{Y^YuwP|ERlWuJ>$kZ&-JrrXi?|YuedalAE9NS$(xWdU(nynXSJQ6j$tB zkw0rkLHO5w^J;DgpOWu7c<7vTy}GqTV1?VV`x6hha0@2gv#@A9-MTWbxBh42xdq%M z^1Eu{ZC5qDp8dS9B0oFzu3fAxXZF#{QD>Eoi{7k>v%K|pzP9j>`e%p#-j|>E-1~;J z={5GO#c($xhvoPqm^48T=da3Oa!Ko>J z8}u){;omJ@{4_DQYop%h#dex=Lc=`V8+v;T_cANXeD{-+@ao!MF1C-Wm908=#_jz- zv-vssPR(lH^KI%&-UFfrHhT2|x)1Io`f^QItIWQ1KrN6X&6n%ik_6wb&uUMVn|E0J z%2vxVmoj{EP-+!#rpe4e4UY&OQ%x7XG%4qa^8Gh+5^osSyh(IoG33bjv1xJ&i;{?D zu-C*KRfmiAmafMQRE*h;bp%CBr99Tp-qOU`B~j*9WZ1M=UOGuu<-@m(AGhnbN6h1R z#5CQj;aI2hgo9VYV&p1E#EamKtylCjciBdhugpWI_)>pdh$b+$+w?O+`p-! zye4o*dd=jwDn_?0^=k&2%XB&-UtOKQ_&mEVU$#C;wL{65D%P#*o>pQ)@ zHJ=~1*Z=n4|A%{a)#}*m( z6POzS9G9xZsBVKRG_ zQSJMXq?;G@dKX%lH*x9yn7zF0>0JFgA5X?^UNE=I+Jk$4ebFlSo=I$%xc$<+FPf$m z&MEITlG$%nc(dL9f)cl}&^m=&A>Ka;dL9bPF8UZO>J`yFFa2EduH3}Un$z3Qb+Fa+ zF)o&oQBZaDv2XYw^tIIOfBCMgIX5S!H3n52-dzycx!T*RbAONJ z?CcG$MIsIFjbbG}RM)G`c<@W-^Tnq6LwXZWWF%>~oGJC%yg4v?pM3c?UYnqMHl+>| zTWlA}hVd%5UC6EYdh+hO43>#|Zr^@sZB@2c`9JGj4>`>Ne}Gv*-T!zu&H=va;rv$#IRs{f{em*{tgK%=>3`q5skjgDkB#?{q)p-@Y_4 zF+gPD+!ro0Lb#sq%5md9a$%><9uLvZ4__qwXGDt`)ug|A;&s)1(xw!bhXFRm?ztZm z_{1hH*7U2|l`=gizU-5a#EB1@XDl|>FPO73|BvO-=l4Pk+B9GLZd{=8xN*m3Q;jn} zRv3O=Hj!h>7t>wAFA_c-YceW$ppkp@t#Oo`>#YJ$7Hx+~wobiW5}_8iG`{}5p}?BJ zV-j-hcH^Sn0~cN{F=Y%?ov9R&V6}BVP}k3yzOh==wCCW- z*$wsoJJNmk&+*x_fJ-_0jZ0tdX3dG^a|$X_N~)`q?e5qA`Z;a$^OHMUAFCCo&6}&f zbDrxh>C1Nt`&s_oTGk+ERTTWh(u4o+wrR7OX5@VK6@2;K?9Jpiv)4at)~nsgCh{}= zlGClU)GehiR%^+-X%um>o($b`qN6oQ_E^r`%UaewqV*M$eJpKet0xyVOE##SPF?!# z>+I&wpFV7#zVw@J(jw!j`Ts)}30~*6%au9t*35qI?*G3Jy{Nh2eJJ4H%G|ijNA2eF z@2A&Y`Y<8n#;z3~s@dDVe7=$&dMtghWPQ}ycMpF)SC!$5$anj?`9ytkh|QTg>C_!U z$60FmZf@AV)x7y=YyE1m|I-E&55H^sTPBonl`%a~xX9|Vdq?QQ>F4F;rfXY8865F!IPP{w zZsjvJzPqZ6R9x1~ojL8US;!9deYVGh_8yU5vRm-*_lp%TwaOmd{@tJdvYvYnON>;5 zu!U&&^WA&;jW^6Ua{qtu(9QGCA4Iftn-B7eF|x|7`SpL#)hXuQ=TCZd3hT=*+Wd5K z&&J=TH4TnJ%aq?O-=w9#_QV;J+8t)T>yI2|o}IAlwnpvG9)# z|FW7dU$`wDZah2Ps5s%_a*4S|Y6Cv~uCG}GsWpd9E#f9%xHnfO37pHU1oFDGFc&W%N#j|@aeNEjV_J#kU!bFP;Z=e3YcHEC` zYRR6-WlJwwDNW>eyD#4yBOP~{%Xxa(^lOJd|K0LaP`OgUPFuS# zoa@ic`Xe5V_BtXzHh*k>XXIsM!xpgo?7aDZo)jAYt^K>_!rKJF<2TPcPdWd{X8Y>n zxqE--%h~PS|Nl!_;Rom4&MNDEe$%}F{AS>@)9h7jjFTU3T9Wil$VYD7ugf<+1)TJ& zi?c5a+7;yb^0I^;tI5k5%I?;iyLFS@QacZ3NY20J{&@NG`sF(%Vx4?j+I+2bw|f1W zB5*b6{-t}2$3Ldk)OGGR)e-plN91{UV(T)a;7X;ELq)TKMUwZPE9I`#Yw0gm{qiVN zbe5{~k)~%MZGTOCXv3vIYOf0^qh zt69%q@6nyMbH489qnCZ^;~uI!l1sYnlks%zO$|${wT?5?&;H3XVKKhCN%@hPYvJCt zTxLA_ha5ka?mVZH@ZqJ@@mp>$KmIJ#li?`&-~2N`RU%(dOZReb*ebiZi?3XM_s(xy zV)~4mUUu6H6WxoGd)=kcP80%roAtvryov`la=s48qEjy`~Fp+OEK#lo+z4?nT5FmF@*c zUPs1lT|NCU-}Rb@0>ahe?|yHP;s5KixoaWg&u6wN*UQyP^v~Xx^-bLxa_L2uU-udx zMYjc~R(ovOP<8%|hSg5tH7sw|)rJW4|37_i_nMu($)^vkU&KD)tDrd3kq!2~CKHxP z&54{=KR0%2{q8yM&XinV_xX#xa#Ev`$EniH@cFOq*=`ViBzi?Yv*Zo}YUU{paM=^;F!l?8}Txi|R~%6e>FGZE2aedPA>H z7sH#>XZh}(a@|wC6YIYztykbFi!o-Ja+B3sXLZP(wfARjJvJw;kfXY|_5-{A`an*7 zZ^nSfU(zn9Ej=9jx_**a)f)}r4b%69EPTFuuS)IZmp`M=tow1rzNYBwTdTyEr}D2$ zbZ`Dw?$@#2-gfWa|A{X@F+JaNrpVyw>DF33mA>hYc@|%e&3X7=-t55k{4cKS2 z?1)^+)3Ew*5M!Wq>lVR>Cnhj2un?RyWy+!4>Ys0zty7L?PWh3S_nfosS-pe9jA&VQhnNVL^S>I{YSjdHMdXqbr35^ITY=juOj_v)<=iNjnT2!t{-r8 z^9Xa1yj1)nJ9(OaanCiC|E9;EF-^Mk?cC02juVr=y=nXV{c=0&MwyQ;GMdN24p{bN z6lw;YZOfQ^We)$X9W6~vyI8e*j%;PAms_bGeD-VGOWsAbv*bTrQO@Gq`F8arPy3x= z+c;MolI)ofaO~0|tKWaK^m}D**;x6Qy_6JSGyLd%K=H17-9px9e$mU$_{-PH{jZK` znYR1qr<57aF*D!3vyz#t#C*ANVyZ_)(_aIvrtoL0Zd7f1-=ih`?bht+49%8zEBh22 zt!(Q%&b)KEdFV#|b>kAAY>tvc4(l}i81}Wbg`c%p(?03i29tw5+xhASTxUujj(-iAuxr`>u1J(9&im&ULdp&=bdGtH= z_Gxe3%$l(C?9Ruj2UFji^Xz?P!nycFTk8T*}nDlTV${LXw|X0d)?Q&u79~AZp~i0L`>$HUv2kwQJeCJ z1I67p&7&kF7r3RLzT%d<=l46tGcNYq%a$^Ps5QGVMXGLa7TtJkM%VNW@;(1l59r@I zui!Va>@nxc5UB2>jCQSXlPB%;A^l|?EuF1d7O+6~*weW0yOm*wc3!Q=b=h&TeXKrY*T>9;j zT==n@j0+1kIyHL#Iw5AZqLuftfd0<>Z>GtyNg6TVcAYRfx1!UZ-0a}UWr%4t3NvN_OS<6KYkx(T-$?W*q-JzK}*&lsMx z!M!|&_oCg_t7i388O)mujS9XEZX2^dE>>@{KetdZhy}GVpO!>rZ?{J%p*R&SB_a!wLX2JdTaH^bMoz&V{$KxBl;o#Z#qONKf8)E->zFUU63$Px`_lNZt76tanb+&r z&8vTFHs4RnfBU(ut8bQ>-uIh%b$;^S(9iF-8TYH_o1EugultJg*wT(Zt`0tHt>>i` zk~R)n!j?(LmMM5OYtAxQc(?lDr_=>fmb*IN_rz(D04NvgC{L6T2$g z&WmrBv*M9zVJ|cAkA6@rmOH2APm%YAg zwExesX|{Kw$~M&}x$C^YsiAe8pRrWxk;Q37uTRWJ{moy0{CvE9{(QUI|K49Mf1kR! zeY45AttEZA6Yrkds2P(k@ju$sXKV4iRc|cTyRW_#nS1`$fiseigPFMs;Etgkhz*FRn(bbD54?d^Jv<7ov)_kQMD z7utF2?5ew!bMLR)!=u#na&hFlkFihuJGrVI7&;CmRBsX8U6E{3S6LU`rdyt_d7+WD z$XRl>*<)YPlA=uY;`k?%ZwD;+K6}@NMeC1VP?6e`mss{??aibdmP5DmI{J3|t}U3z zJ@44pyE6~%jL2%5xa)w}{M2dsTkBs4-hbb|_<|aPlv4=*u?0=6Y!jT^+XUE>#I4ur z1>X$yba9W|`te+LMvhSR{TpV-&T`*#HaR$tQO{^id$U2EAoqp7V;KpP9hy0>GvAy2 z^n(8qxdTnPdjziqxG*}JwQOJ*LBuYBxi_f01FfWX??T&CJMxm_AA}x2qOTn0=q+U+T}(0-P#b|L5rxaGtoH@W@K+|6Kkgfs^Ty z&vce8pK-El(!7+7cfYUws6Ovle$n$2g}s6L$D=yxxAKU)?$B@)OVG8~wzElFeQa8t zaYo=FYqtcRg$50s29r$ZE!Nm`deNWX_apu>te91xVAGMK;@G&VP`!#Xz%gg5@VQen z_k~{)ZK#hj{JN;wQ^xN2;}orR@kI+cPkfDE`Tp~+EbFw(Hal|k#VajiZ>;!OwEx&; z{p%HvK4kl+&#m9?*B`&)ZL4$2?nUo8zUVG^w>rY$^&yQvl^o%dmpc#ef8#ACGk?8n2nHx_mdza0+>{Gp0$p6PmI=#G& zG24vZEj!y4<7yVs)3_sEdri}Z7b&ll{)c2onM{6nz4yV}pC2{j-)5J$UECJDu>So{ zg~A8t9b!e8i<{!se3LIv(zvFu$KhB4>z0{Y-KE3*^KARS>@Sx)xU6~M@vqXyt@hQv z+a(k)e}AuCT~%#W^{?ZPcenTF*K@b5T6}EJ=PvfQ-`OeyIXG`TU49{BQs{)P3Ei?n z5(N`|D__i;Q#x00f#SrK^-gQrb8nW3O;P^W`EE)dkL~j1ia!Dxn#z!Y_@}}HGS^u3vWo?-uV5yM9G0AbJWZ3+w9Zm=N0qLJ+SKJJMNs%LZOWH zZ9HW&Ym64nHB6t`!+Pw=6tiTlXl*fr{;M-)?_(^;f0OJiYxm{iQ8Ekw;g_4 za4Nd8{`szTnJN?BEc|}5Ii|($wT_bdj(0`fE|Wj_?td|{@?k_f@9ww1nlrB%)ty{W zy7ZOC4DoZN$F>JcFShx~v&By6 zZk~9!yX5ME*j&9=yj(^X!&y&nULXJT&FWphLg&U_yt@9C&iUBCTIummUx%~qR{F5| z&a?2JzvG{p?LT$*zt-M|P8HnE8`?J~<`r`N7TGT8VXd~=vUhPMN z16N!v)#iA<^={9}*ss$+7H;1Aeg>m23&;0csRv~bL|uy2k*jYrQmRisXW+{6c~?cC zz&`7Gl&|EH&>=?iSi+S9H7b z8~dI==MTu@A_{^Cl5a}kD8IjRCe6LrfqX!NRyeqfY{8f-S3aqH`U8J zN*y`2WwGrFBZI`|qZ8J0DLqs5GpVVOGxNG9_hRMZrH|JMEIe_Yxov_@c$|Y@+O-9H zezp1CZ#|mG`EBjw69O~YdJY;-V%(N8Rb01q?_W!yuQH;UU1olVgT|o< zp5*n}&;610^7+KluoOA%pna^&Ny)<9uRjabNA;vIvoAIfz0AWp``EP&lhvZ-8G+BO1^#iJ9pxp z6X8O-yWf2id^h21CXZrtbeg<<-Jd^)KUckuU%`=+y(crhXX%0*pN{qU*wqaUnAa%ja!ux>Sy#;?Ol%Y{e1zRkhe9zb@OC~#wE&lC}jgO_WL`v9syz0YS3%42zPmPEdSD5FX zq&j(lO_y+wFAEFv`%_Kc;bOAql_$FY(waAEb=Bk~;g$DXe5IUxMCGIPwlTg9jhCL} zx4r1!h9}_*J98bfeZnrfePPX+m9g*8*39bWvfZDrbr^ov3R^1ODUtmr$(LF9c|`ET zx^wfc*{V)_`$bDut;D+C;$!p#reyB03#{AOE*1C}ypMXH%U*ISJI`#!*Y$fg+cLH^ zO=nF#`tO)|ta-)5AJcxfe)zajRqoTiciXLV_B;NrFY3;)3vkov5N2FDOWNw9-MXbu zx69~F`1*0ftMvtkeqOn{t>tX)ud252X>Y7|^0Zvkn08`c#}t{Pb5=J0=e4X~{-|-w z;TcCintx!vFw6VzPT_(TJ?E$T^Q+usdRW5j?D_kf_vWMhWfR^i_BFCdDqNO3*QG7r z-tqZM8~0des|dC@uxvpKV|ez_dLwvUBn34e9tUE7s{CuVx- zY3x%mkh%Nq)}!DLEGL`GrKF2Yc$XMH?AyJsLU)0-=mt6MPhTs(96o&c^zQ55?QQJ! zr*=qw(69e?eZ&5Xr%o(4l5x53cC>M`guPA1q2sJc=chgKcWnFYVAPiUs7QK4`K$!K zn-YhPf4y@fgZ&3DdxHU6+ei7v8?1-KRzGd34dr5Ta@CmY@rLhB8hha4=eF9+$5wH_ zo%m6w*hY4XL3Q;+zvlR&#R75n?%D3yB3$&SYxfCropLkg`U*a-hy;~e3eQ9ib#YBy z_A>Cv$5lNFH(AvM{cR^IeSF;Y%B$2phq2b^E|c(`4G9Z!emrWFwwl##+WGolcawL& zP5`^Fwp7yr>B+r90s-7>A02!yx}!t>^P$siI=oD7{}i`qd4>ojq_f|$&A64c&|=?x z{;rJD!y*??&16|6%Tn*5u*vaYnl+2A(WPH=dcR(9)O7A>aNMM7mT4H$vzmeXvU5y( z*v}{CpC=2QYkcw{={?g@@!LJ?g=g&!U*6BJ5FDZBxij#M?mt`SM)unQ{ypzQtHXbs zT(OUpxlr+Zq58q|CoXPUaMVr7baTn-^F^x{A9!#;<>J+dML&Ib!}H1x)IYc1TWx*% z{#J!|YQbCj%FSO_OyXE3xuWy$?#~zW@7G>`cX9JZ5y|-V!8bYD$|) z#vaV(V=nEnMN1|lh+X=1r$|;oVL|3?Pu|cpq3DR}_~|Fg-PX&`i@QH>e|_bT!j&hp z8bhPXC%-uJRqc#bpZ#tA=+YS~mL;#5K3-$}6)D~kEG}@`#lO8QaQ7Nti|ci!b6y8; z|6Kp!XXeqx?yc7io_Cd37n)e+@=AKW_Ne7uZ##F##3=nv$K|%kva+5_EQ&m{7nwf@ z^0&)h89rG)A;4MiPOCD%`9pRt1utv&TcQM3{UgP!eJ#s((e5_n^@A&_p?_LJqKC@ug!=0;^)XSdf{_f#pal@m*%Cp&s&r6Iu z?8xTWa>a|&JB)443L89Emy_6F@zL$>l5V{tJAD=J&ANW_X{%||%{%9mzCY5sepxML zdrrL))2nH{xsMMY>2-Ow?u?zIoAKont%n&G{@pQ8NHHRL(ed1p8>ZEY8g|F@4Z5m% z?i}r$_clk$Uaha*H&5x#hM!l;`Q>MS4Nh-aaB;4rsAf~ZmNT1$FWz=dnPJNx80(dP znybzyO`zp^WO}0d(oCxok3~-TvbXH=^-a4ub$+(pj1xYgpDa3EaPr%q7WK6|YcIdiUamiX zdfU|V;rnEAoTA_Cxj(Dz`)mFGPoI7Ae^LKuRrvkYzv2bheyT=JtiPL{^Ys7i@W-uw zBAShJ%+4g4`rF&>`IGC|(PsMdrrW#~Vb*ibGR~EhW^<716E!&ThkNz{qup28>XYaF z|FJ7?)2`6x``{J%PJ zrcuq~Jc;^at|upIO-?;NSuSjy=ogN6H@VAqUHA1g(Cs&KsJqp zuQzf?d0sp>e(rbiPtzM%pLwXKsO=DXv({|?IlcEUs#%Wn*Y-R87Gq1&=38KJZewzQ zS0kHPVW&X0$PV5W<}A@wM{_bJzq}gT7xU9Wd=d9DHI4sTd*t0^Rj;mD@_L8!+rAqw zzkWC$lz64}?ib7bYXi)sKikLe5PIHVG)qC=lc}Tr#Lk%2Pudn*wl~S;t=qs;|1Bnj zeNFNI+u5(rMd3m{!%@8RR+_O^C4c~6C9j4bP0l=nLFJaLcb zef+_da@gv*_UY*_FwYUYRA= zc^+=ME4R|zwvx+NZO$fx$X}0=>-8tI9CXlf(ORE$r@&;t)h7>$pYLxhDZgwUvuA?m z1;6R<&rbe-^yX|;wK)RotYkRiq!a#~6?$|l@V96@i<8a4Ef4IcghV=a#3i_w6-?wk zcq;2o^-6}ttR20UpF(Ux+zy)DlwE3f_WeXT))NZlru#SD)RS1NwQ{cV>bb^IyRW9! z-&46eM_lbJ!^epl+I&5&3%=XU){@vE+P_NOu(MP6qM_L=WnPwM#*>%#3GLk|(XmOQ zMb7Q{A!eAdT7~seC@>tBc2_ud~?!>`E|?s;)^94?=II+G!H4Sx14+- zLM$cxz3=ww$`9h3eti76UU$LNEx%Q^$#*Ms3eEd-(|PF=f45`)*w{B%xo0eijlFj|R4b^+^p3ZiO zdhlxPy}YyAt^bA>-`M7O&#>U??4eFF*Z0Z+}+3L+#qkZ|SRF z{kvxLDB{!MdwYBjSC;+V8@}dM{fbi45Pspd_bcOuy#x1SDNwKmY%iovAOEWbnj>v}_i&TJ3S>@s4u_s+VGvSyrfd#M`CL zexb*=L#(kv-D8KERxm@5zP)pN;FS8mClB?giKtGPDbCF*$szb+y9rnQk58Kt9=W)z zsy%l3_3!6}Kfm66{9k7ebE24|V^n9Q3#-ij&G!>a z>#Jf|4kcSLbi2G&^Z60wx+CEFhghRPwZvEKZw|KYG2VCL(9~JXO$_a>yb<$v{p;I4 zf4bVmdvoRqH9A_K4Cj8tQJs_>dNuUKiYxJdRkDxFcim{M?pkC0ig)79o#HkPnOc)m zI?f+Rsah&6sj|jaT8=rw<=C!MKaVdzzxr#*&Eu~1DapG}^{!S}vt?zQnf0LwGq1SV z9}5ojJ-=ak-hCIBpK5G!PUqgEmLpEk}c zT_PIyvtM^Q@9U6z%`Jya%-4HP*!4%=kaz8qw?-fDR&vb}zfsM#{A7LC#y|XP{+_qb z7dURNsJ`w~k#2w4)Ree0x{`r!f0j+V@OXn=qSox0MQ40@qjKV-SGS)^?cbp=>t#l~ z=eeBX2x%`hjvcic*-eUKF1f!Qbsn4S{%SR|N5P>!H_`IRFPExq?1j(b*=!fT5R9#L zF)!q~;y&fJuvaa^q6hz+4lXIEU%Z)d*T!&;i?2fTe|PVXUeLK?e=pP7trkE1R<#|w znYs7!dcP;Pxg)o{4BK?lj;FrAbG|Jf8&`?T8>tDs5u4|8ml`cm*1lnGa5mEB;V!%G zllm^Qi<`_d7zI}|sB^WR$vDT`k<`QDeMrNi?`Y>t8SRW1>%~42TO?;~Ysrt6KVI*f z-1+5-pKr;_1CEzmZDU+QW==A=qVHzb$7PXluj55{+tn#QM7gA{UR2P#If2(~eyXcb zwAF^qa?kdqL~Yos_#s`s*yKZ}!o}YTr#G1&y4uGsvMV}GK3JgS-s+1_71kxJ?&&Uy z%JQ3e%X73Ll=*UbOqtq~k`mc`M$}kJ}~pVwz$1ex|A)+y{=v_fEFi z)Y|Cd9(KJtz_UVnyK**E33*>uGr2e=#C$Qy2Z>o>=-Lg*Gx?daah|3(!*d^Tj_{Z|Z!U;!$ z{F!Z>-Ry%&$RSz(O>XO1 z9%)TjnCMp5K1Y}T_H8|uQ_fwvlQ`K{PdhTZLn*wN`FqBB&--su=AANFAfcP{i09z9 ziDg^`dve4c#ZRwMt>qTx?M}P6eXZJhKX;o)&kjwCIsQid=IgZmshwHpCjU&cxH{EY z?uDc9R{pmKEwwvNsrWrEt=|z~Rk$r~_Uifzp0;{z4{LoE?P={^td+s`@!;G&N@BBi z*EpB)2MbyhR7>8l{`9c*^o*O&HvOC}m~uK{{|bfADt`X{dR8o_j=ep$mm{y?^}6PI zx&Mq;Ihwdz6ni*rQg<{3ot?aK${U$ioGR;DvfXX6eB%w84j!54ykzPd?$fX9muTL+ z`-}1NwO^Xo;x7LUo9y-_zFue99*z?59-T$Y(S`-q0UoK4e+W$k0 z7C~Ql-ju7E2&mfolzXn?se3I{6U$ULc}{=*m%4e{>vvDMBT-lqu~vGVa_s`KV~lEf?kf^N;st z&;0SvU?*V*x6>GY6 zf6E+;^|(_1@oLP!&GGyHPQATR%l%u$8l8<>dMcMWcL`ftzcmj(xbW1%PkzyhvL0T) zU-IN;%~RFzd+BGdU%6lU>)X?=Sbduy{hg-we+le;oE=|nZu4wL@BhxjF>@SJBdw(m zJji`|y3ciu;d$Stf?dAL|JIlr#;;mz<7+VOXlVEOXYEnjf-~#=ThB*lUtQs%Jon0W zp{Kv3d0s5l3|#4QGqYf#pQ_YTHoMsiuI_P}Z0qv=hTcX0{(O7e{ad6B;^z0{9K6T* zzHDCV%EjA%Pg|;Cb3n)YQ{u14X}dOmi2W+`DxmG!uNxQqER?UbIBz?%@_)|KEW^p` z@_(*!xP8fVPdL|_H-4!H=Z4nXw$6TY^!mPqVJ*T*yLsl{-)~!Uf6>E)EjQXX_h`)M zHts0aTv2dIzj15Pj!S0_J+W94(LQU|;VX}`-p?o%f9()FeUjl`^LEVAIa&YYWzWgY%9GXQwqLB>w`KO9q!;J< z0#30kT{~~b>5!va`dsvzB3Qq?=M-AZc#3-nnc3rcE>7?!LE5Dr#K-QN?J>#;h|P2u># z;&(Tv&tl(xIiUVFlehXmq5nKqQypux`xa?`k$AHI!Rd6Jqi=k?<=JoAg}bjVc_c6X z@5H2r+rJ)vKHRSQeZE7FHv6~zp}O}wBV_zC!}J~M&(uxwV=NQ@A)K*NUu4eIs(bM* z0$E3&pZMa^do4QpBe!3{zVG)pewelz(G75f-UtsF%Mu@s`Vkh%4q# z_WTumVrhJ0hkfuSVRw(S^7WyHmrBK!`t>_Zk)6sb_)27>r|-iR0z#S!R+Ccy^l8~? z{X3kvkU`nx!dZ^B3(SP3WF#(BT=eV0)5ZKQmnMguD$bqXR=;YJ-F}cGLH(hOehSs~6 z^=tO!iB_z>vU1+qds_?F9nCj&I+So)VD;mySr;F=n8g{kiv^tX+-oLXZBestjlP2wy!?CjHi`b=<#WDXUKx6QQDFA|Qbwa==Bdmxa-&r~t_ZwvDrLs0lohF$ z{8JYhK2%zIhsC@^{Van=MDP{nxP(Ae^$7pT6aP)(HJG&~{mL;3KIc_8szfI5ohZ+} zt%9{+PWCgso;-=k&nL>&@9XFK^2k#9h3i|5Y+D|&D5gnfr(R6BxZd1reP5rE?neio zw~M@H%!`X~%#_?0)RlJXZQ1M}pDMTR=s2R9zWC}Xr>xog4(~ty=f|Iif*IS}=im0& zvX4=`Rn%qW{T7YP|0^T#@T0O{W{l+6?;*^!SeLwc(RI9J8uXd0~EKg>~lvmXv*l zlX=dbeySv%V7aAa&XFg2UHxCaKM@o=p8ESiScGAunv%=z_u^OX%iWKg9_J>qG3{_% z+`a5QE=JzPYh>874?cSQELi^kzo!qArR$RucHjQDWJ6Bw8f}G`B@GEa((9*$9`6LO=ifd;0O=+mBE0-sb0D8@XV2Ynw*Gip>oZTw;$jFKUl?knXaQ z=U@Eno8{;AUpxJ)+Ns4C$`kA69Qy9erHh ze?R=Vmt6=8DPjorbtADfFocz7f<9lHC8JW`9OLJ%Z6p4NGz~^Mo#dO=Ffr^3zYfii{9HF>9;=r@w?~0?F$%{&RgC3I;%(S;*Qxo zUz=Mh#M2-2z0=&2pm0P|%={(mTS=ogy6eT3eLu&oab&lJ){6IY`48|Ke9PT)*eYZn*3K7-JZ!;X9CWEET=LILgI`R+j_h(f8JDfr?YSYLS9&S%soR#A zcLm+*#~yF6wz&U}QTnBBgw=`rlRhxs2|oDTIe&4CO9OXPi0y=jhwt{!lC%H(`SJ2r zR=Z0LZ#$=7yybfQn5~e#GvhzW*}RvUg<5^DVnuI?9ua`7J-wt8BO9pdH9g33daINwZz@Ir`AuII&YFo3Ev;POTj!b zE*~PDRWkYX73%r+dw6P{S`;c@^o#opfAt^px3&i=8Z#ez@K&h&JkoPP% z3TLt`s>rJr?tHXZ?&^}JI4`NnXDSU(=iF@m+YqUCWzKxTgyg5&1rMI(=Uc$-sK}D+ zRc`&McEgsY0~wO%pDNl+o1Dp(Z*-Pfa=Vu4n+%pz)z;?Cvy_|WUgh*Gx?1S#IP`9%VMMIH4&q$3lHA=*CTvoqK#VXVCFFXo$`C6^H zHMeV&b}K$V@4RAqM+RH@ysLNXRV~ZB`FE#UMQ<~iqOn~n@r$5L`Ik(o-k8uc=MJ87 zOrGB5t}Mmv`*==Q(Bb)BH-z`T&Y4;(vBt`zV$~#*WvkxhW#%hy$ckd#EY)x`Icjv_jO-~E1xefw>M9$T(-RDmYw6I{IyPt_Ukz$ z@hnki^W8V^+?sB03n|0v+z(wgbp?p!#RkaR+tut3VCS3da=<;;z;JHHVa?#i-Ip9( zW^%t5)45!4-j%~;ba_j{GTrlWOVyd(MG)1jhztb?d zwOY}F{q)>Bc^BjUbQbv@cU@v*7Ms5^tI2Beu60efj@ zE9m(zkJs3utN&^Kst+!YA~+6RlG42>+Bi|}Ri9Q|lzjizKg*c5ewy1=y{ch}P+s@- ztxune9esW4QhB`oz0@ra=C2BPXuWrt)~2GSR=xI@ozgSo6GONvZx?(G-~ZV@v0y^c7`s@EQp1t?hwY}UZXWBI3n6FKD_?7S96{@JL z`~TzDt`8gktlTGG{5w>_^5O{=>j!5pMtzxWV*GTv{TKTMhdd`gKQOud@5F4)Zv_ml zMq(U=dGF#T{`q_QvGyb7ZCorouZkrfJzKq_ezx{*l5KAl)*WP?wetO{`<1^- zYJ>_av}L2F<>|)doJ>q>yd_njVZyXvYIu!Z7rVO>hq~>9sJ%OuGCTHlS-+HQzID*S zgF{j996QssKXQBI<1Rc`Hrx~`aN^#B3k88LbJv~p_&@(g_!HODZksqbrh8oFesoOY zT~$KIbA|eO4_+obTPm}g``z_PQ+aO9yK_*b{^jy31tn=M?<#Hy{t@*!=Nwg;pH@HX z?xg9qGd%RAiai-Qucw6cai2b-Icr(PoM&4&tkT0XcP>q0*WAR9<=E zz^g-ajwv^eZa=eEccj|NmceQ|sTW8V5ABHne>>oAgWP zRDRd*)e{>`O*XV~ol9c>T=MT-$R-u0-^QZx`g>n6P5SfEePiaP58^+QE%)avGR=$s z{{FrP!(GLP`MaKZZ;CupQD0-ePex;EsZ7-tj;u_jAFuN#H9U6zdTZH(>+7doezoP) zUL#2}vm?oAM&r@IBC{!118Z;8|BC96 z{j)OX#Op=Bzx?`BxKu_dx2i(&No0ogGp2x+(9Y;@1!fi5@7cFJ<2c!O&MZ}Uq1m+6 zLceT-#rMteaBN^@S@uSGYb>YcL$meDGwcjX-0zg^OLF(yyJ+Xn4ZY`Usw?c@#mmpL z(^E-p&$iQEA*d4RwvF%PGQ-`Q{jTd)FRYI-JiE$3k1@aERO*}P&m9{!p5A(}bswi~ zj{l@=j_$)7*9fe?|9*v7bcTwp!*)k|P3yD&jjt{{@zb`iv~ICX#)FD~dzP&Kc0(pr zc|Dt37T?=**Ke}T)%dVM>hXrnc?auk&rV)`V~Uh47gI|7-TynM?`Ks%ccY=hRpr;! zxt5kK-St(uKP(V^_ESySMc*=cc*aC4N5iIB@mG3dv7%CH@=lW?8Xj z@e%hEkC}wnY*K5kT(HrUU3{qf;~a}P;n~ZVJU+10U_N8-yoXJx%3=2-woVoi$T6Ag z>eW*}dx6S*7oDxo5A0r1$}_KT>W2yC6$atUW_6zX)5|cSH^#>011y(;i7sLuGwyZcfr{e0l%ir&1E6eYz`S;_?zlU!N85>A&H&h}Q$J?phesvvolb&U3^@3Us_dKu1edRaL~f~23bu)E^J2FL8? z>Ua~sr2NxgTi^Tr-H{;JSg(`uquW>G^NZgXiVhyT#|fsd-I5BmIGUcDQPtty)j_+A^OH-|hZ=eJJ1Gtj|y6?Sx3w2D_B_{nldcmgOm1SSTKWRpb&-e3c=e?cO692b;TIrTa z4O3)~@}0RRB_$-lwXTo%+K(Sb*CzO8@ZJ6!ZvXk~$G2}^UjBZ%VP;~^>@PP~Z)>Z( z_q#G+i|(Sd{ilC@X?T>(QgHZsKr)kd#ZKj{$Olg!N=aL9PTy#~?Gyu-4o8H;9Jy%b zKW&d#i~6{Y^cz;Dy}lhUrqeR9;a%Ua(3$m`N{?SW7hBQ!A*{_v{n1Yk*Ul*y%x`dT zEaZsV$Z%z??Z#Kzc<(F^F4lc>ne*^fh54dyd^q@|gcDEqt$ediV)Kz@hj^Q%mYkS> zZqBmmlY*1_n8SPD{=IOz?$}yI=QMv4we@ zC~~R(%G^dvoe9(YSe|TATX%^0!Ui$+!o)}!>31>H^&VZ0tB>8+_+GsHa)cptOtqMrT#J(ubhiJ8ybyRuE)TC?NUu4bqEiKpJIIGz6G8EZqLRPe(oPp7)f zVo%c6b~vZAWu1BDIYZ5<^>WNxCwB!&Sk>h#-rOdBH)sKCMMLa%u1lgu4lIhVJ}1Q7 zZk0IOu%TY6uF%y-Y~%V2){d+Go|E>oMWy__*r*o0=%T>Zp6?T%&Wil5Qv2nQ!)^@| zv()q>iyS_0C~ErpPJ!D@=k5mY%Q{#+3qP7_S}|Lpu1k+dENw9 zdBHo)D>&F(mZ%?`T;AiWKk4%3C@y#99g4Bv=A{+>mGw}too3g&@bPapZms9d5~~dB z6dv8Zxl8cfJc(rgd$|h@S3Z2MF6w?TmOa&0YsJzU>oRol?{sw33IJOJhgX zoPF_2GL5|+6{|5Jeo@u0dkpK8RK$I^R7tIU%k|e$G;p67oAS-a z?5tl7i)4np)|;^`iO0!$lWF4h5YCIrvsVOM;#e)7eoZm$bGSv2sm6hN9b=`osZT`h zxFfx!J1#NFdCN|&UAA8~?4bDTkP0(yv+BuKuSzza-x~bMWT$4s&FykB9^bD=+PVW+dG@TYZ+}>=I!6kT&!bK^)Mvp#`E@7zXVsv zH$7b@E8Ak=UQ&Nbr#7c=GUN3?nuB_HeqS8O$hp?e)D1$D%`BB8K~T zg1X+dWSd`~V6U5&d1@bgc>|67gcgtjaE z`pmuUz=j5AeZSq^Ww*Frd}jK-N8nN9-0~;BGJR7F8-AH5>*UF-s_&S0Xno4^hk2G^ z3v;vA$hnyZo|h@*31&FEyD=@!CH~Yy!*i=`-`?UVpI}qr>t-##Wt-Fg>E+cmZQ&*% z_nVbiyIGD%oL;}*INfN;8A-|Osi`>%mVEqEOU^|oHf-Z|Jl}EmeZ#dycLfV4vd*@g zkeyJpVQn72?(`;(i%brTJ7emVrZzLT8BKbX@Kg1g?(Dx7zUt}El^Is=>fT{u$K}3x zUcck&4`(GdAGp8sI>XZ`&Lw5XbCS(ZOfYF}_+BfkSQ(IuGVKWv?t29fk zZoB0XIdhAj)O#McGykQt*Wc&Q<>+$%w?U5Q>$yhV8T>lieteX14G0Q6)iXU>cXRF9 zHnRzhIwyS+<(NBTmL&17*|qntU(XcT>AO4Xoe%0X-`}w0W_}F+Ps6rnVrP0@HAL~x zDX4G|69aA*58`kE&Gr=;}+jHBiVyBF`Ex-UyuLs@a5aPzgt7p7uUVG z^Kwg=h2ZWr@gG?>nH$ZkTC5*yG|x?lU;m(6ip|>XJDPQ;Z1dXtEb~y)x<8qZrqC8%0mt6n=N~1m3kYa+ zE(u_nleK0Vw;)%DoS2|d6YJlXt3`Q3UM!mQ(dpR53U>*om0OCKCkjjnQv0ZCKWU-6 z(9y5U6LuYc%=`F4?$hTv9YH@OKd+m;qI!GE{~uw`_fPwH{k!gJJ}%4HzlYXyE9utv zewaOp(eM!C(f8fC>L10|9k1VY?R_KXf0r)jH3xo7xg|IKUSi_67x$dbZV@=7qI7^& zH*6Q5u6&r))*Xi*DsegGi?nchPiCCRyFp;L>7?IJe|{EHC@d}767zXw{?tXAPfD!r zYh>pLzig=TOjVv!|MH~roJR%{muh@&r|tjxsl2|n@(#nr89a`W$D4cuBr~@0{B3G46#%PTKd!hnMpwJOA3VXqHRj-9Jy?E-s4hu`S+r z#<=0bg7leoQx+-T-udItpHJUDeb^E*t>rd5>vDsW!N1S72FCR~=N7l^{nWE+O=*Yf z>9#<*nH7J3PgiBgx*;ttRrR~!-_&DwpChPCL zl+!<>KG)RtckAv~LHqiaA1>*C>c@1_e5GWbWz^G|M*m~Op8x*6^y9nV=ht(aAKaj@ z;M?c>5=YYZ*SBAN`LMot;kK-EEvyMsEhMJ)-2Z-Tq33&*>!kwkFTJ>O>F(q`U&@v| z*I3F~#LM{O)7>IP*2{+i>)C&C8SApe*&L3%l_2ul@%%F5`8C!zwq6K$k!~F{spH+* zMRBi8`?j#`_%5SyXu505fr~F4@-+6&tzWptcpJ-%d3!vhHfZ1ZSns!@eeT;zcJ~RU zam@#6s<(c;tQBp2TI>94ZU==W{NBf=ChZD$iFh#e5BIVM%(Z6(rEPBX6kfSe$)>A^ ziFhEOyjHhpMO@Oxpx1}~-|_obk~X)hMc~o`k<6{28{kp`OVTt{g z+^UF)7qy?RtPfJ)i_bK)Ea6QOY2nZI{~xw*#%y_w7$(Wp%eMXPy<&Q8Q^UUX&)(lP zs`~TkQkKqvbI;C2GMw>~l6m~+!u+%8g-y3zZylYvFSF{@+z?`ul1yU zdcDZwBaYvWZ)8i{d02ao%JLJ3FDOPa^Gsuz@YVX_qj|@U_0G}RTJI|BFCbR(#8xcb z%ue-9$_&?anS7$9YUvjbNT`096qgoO;cD|t_Gj9$dtNHV`4$cHl+JMSg?VKsE4%W2 zYdn|OFnL$a_KyAk-+gZS8xY{L$2@rL!V5=z`z3A!d^GbrD*0>bmQ8(&T@CG)HP*d$ zG_9M)Evl3uzk@B0Bu}lMTDGC-bO{f)?&2#pF<<8NDZJ*Jqy2IghfzaT>tt(l znXHBwg9i+T?6QI8Pu%#oBu@UHA0xA1Pi8Z}%(bSSADF~mb>?a`KQIvq?Wwu%$(Yoa z_pb0)x;5X4wkO-WRW!cVO_DyjST}t0^Wu(uH-ZmLlk{(&p|ix#v8J!4c;1|&^#y)C ztZZ6bM{kEbRW~@y`Sf8@>38Apisxe!V-jDizP`qIQRpI>1Q$Is*JbO!>{#xv&+YeR zvNE^r-x|wHS?^BD9C+9uwawH`|Mpe`Cz+c}S~vHl$1x>;m&g{{@T%d+(SzH#XY69G zGV9&iGOe)HBg@myVV>NvNexUk$|v5qxG>Z+>i_PVav&noV%DQcznMQQe{a9_-76&# z#n%VkcN<*bscVY$5)x~Cxlhk*(%MqbmYzjNcSbNTITrG867$(vhJ~>Y1a)hF$Q`>E zkeu_N%5|aq#MQ@^ypZ-dY{B*f4IIvgF(e*`|K@`7l`*ZdNp17a=u(*rGvr|Lw9)}tDTI0+TLvOY->Nk za?SVnlAp3QXO8)4Kb3baQe?mBVz8*dIB~<05ThAWF0>h!&oK@@^5g2I-v`~*^KQt* z9gY+hWjMZ0Por&mQ+oY{JujLKZZ!TFcM8?uJA^4U1l?x8~TbQ`>K8ZN62s`BvBFTS^Nn9!X8GlUTcQ(VogXl?fLOrg7Xg zY26&k6uhDKz1!5icKi4I{_x{^yT1H=u_A_muaez*@}l|g{yK_GuAOqU@dtDJOScEQ zKHt(mO`kmfhei)ifl`BP!d>Ubb*tA{)W3ooIg*F;#s2zIPs1 zeAMZ7|cnJ{FA@=$F#Fd zYuLGUyH~wwP5juiXew{St~F6xPtBhB;-R|kME3JRVsrOwo;u0z^9p)bek%ZhZ#$m;<<>)T4wcf-^8WgDmBVDIlYM1k@?pe z_Ojn};faRke?`C7-mP5p_Q*`u)EK4{1rJta2?%I(G6;V9`BTk|-E!aOTJLi#CO3_4 zAGKa2zChzSZ{2CWG_!Da$<|YcqU)`4!aVmnHS>#Yx;w`-cw<<{?YXjylbnumOi)=Wv3P_Ze#WD?{9B4K4h`z@0Puf-8#>(-&mZTCiy4n$L-tRY_0Y6H@(>wR{fl0 z%CbW2;cof)c3U}EIUc%9UA&n|lKc3|1&gL881x}Vf^So{>~37PiEH8&7aM^!0^HW^Qx~pI|ITqbSkg*+aYkyy87pUdXVbUkvs@>1 zObC$qZ{E(#kj@gEIMw7qY4hH^8$0WxZm>ic+HLst<^9yRLVrHqU-Z}1)%r!N+PaL4 z33*yM%cfVX=kLE?`}5!3*S8-(FMq7?e@{>K=Wf9*(E+7=x|5%O+M_N%FMY%2u_*s?6jtY&dt7SAR%+;1g_RZhF=dYsVvI(b6IXkZh9_;wZyqMc9VTQ&V z?SguZ>!(esm#=^NL%zFmiq!xZ>MI4l@t5PmZ3qd)wkSE;l|m6=xs1ETl1~jA?ah^E8k0 zBlGijMvI^My!wP0-_x!_QdTwcVx5&qb~XZZn*5;jzM39iE~Mu_>3Nn7qTD)`*8r zO5DqG-S2imoAvy!*Pl;6e)PnT*etU{uFNvcc-4E%?^7 zce~q9{K}Bw=gH?`ceA)+O6tw#__B<~jt8;xrpt74vo$3N&SX0OV&?AtlD3yOnG+?} ze>d8>kkR6tRe`|Vv!~sq?*dSlsyKFUwiBzIi*&s6Nhokie|v;&5Q+N7iqSIia7` z`1(y={%iX9w=!_%uD$!G@814=zMOcSRehFtw6nK;{o|~~d7kCFvb|TcxK?TXPMYr5 zE^^Z(BXC0fDyPexsqxR>zkT@farWx~z5^-IU*yCtPOA1vzW@9ahryDKAN-`dpVu#V zZ@0zeCnx{m1L`_emmZ|vTFmTUT79|e`44}s315rey?pric`L*A{Px0Kv!Zsg$VZvB zKCL`Ehxb7FLe0DNKEiJ;UoA2FKJ8nLx52e}DwfF^oaMj2eY?};uYZp1&BjW)@z(V0X0q_2(L|JozB8>pQ+lc3+lpD*kPl zIx+lu-RVbL7(Cw!J5_t$w@WCzmb>Mq{QU3(c05~U!i03@K3>1;WkdaRuPevrbUyYx z{n6*Hz!!@*CCYW>;tRHL$-Yu4UHnB=JRxGWv0nb0z}J8F)Ym-!w;(e`GxpNfS1;eD zh2&;d?z??v!~bNXIkRuQ`JOxB#Gc$KM|Z|uRQi18dw1U?apmC1`R~o`&Hi*|KlhJH z`DnkT_JL-1yUw~uo20^R`*n&oo~S>f#GhJPwtL6#|60KyZKVJD^Ih|onYzU(pC`G>oqF{~KIFB0&G-8S6Yk6LF{wL-uM>NJaKn>@^Bj5e)o>Mn`zJmz+BzcJi>xE)^X`&v|?;DWZ}u`$dK3`Pkg6 z3{>qYkN>G+dFSVkIG>EX^3z-nrAf>uPcDj_g$_8m;~H;BIM z6=~>t$*y3MzWq#{ox4cYenu9okIQA3Bd8U8tfYBh#|Rgy~N8X6Z*V z$z_Yyn}5lfGPjdsGVhG<-TW`h<^9v<3oQ-m&ko& zGnZwl(fYcBwb+HVSmG1cT4eyUkMHG|6F+jG)T&Ri?p{ zRg#>hi?*DOywIe4FXe&rCjuoGH?Kom|L`)q2|mB0iok zttp-MNAjxAi__a=a<6~g5R_*fBvYhckh8$y{eg35Bo-6~Sh`CUPP7qPqph)a65rn_ zaf?G&D&!~Syh|vSvamQFT`y#o6sKKmsLxiUeelM>MFV8 z~dUd|d{Z+E~lK|L!rzvC{XcWcgyt8^J50O2a52BolsfKIKP5d@r+kU=nU<8VIuYdx z6IV89w0b5L%PzJG57@B$`uFqPe5(pQROOS`*@QR7JxuNCk(hYQOejpb(WO^eo7~aLaAkh6$>vY4Uk17oUie zb-R6UN7!GR$|-%dhw7_eb#1y6B*1idh26f^c_wF$M$Xt$sBG#jm+rpv$c4VvddWbu zw-p_Uhf_Cy*=Tt#!*(zCU4uzYYqqOuKYgNeQsO|uPH{aCc~fs=H{&Ql1*Su*6Y@OY zg?4pKnAEBfru1Or*C%&YUh(6rx$1f7iOQ`DnkR1-B=oLo(?2S~`@1Nlo=4^K9Dy5e zV{Tp5O!P3bu4t;Z))qL|>3S}85|6m`DS_PBH7fFflcT;|{eE|ofysZ^uD*9sIq`?r^#5I_ zMR)W+-8H-)J2`*f!T6}s_n!B7nSTRMAfQKt+UJ9y~CWjYKMbD`M(*=uPij~ zFI>mFSi)xU(mxy5UDf_veMKp>{~~iFM;O}@uJx`0^|^o2yy7QGe((`HtNBM)y3};J z`u#>J;jjIYD-D)NS__9=wbZKWjScYBMmHG8@Vv|m*Gqei`NeNy! z?dt4Qzhy|#kD>E6D(+h2c`d|?n1 z*L7*J!JRyrxvg5GIF8n@W=aC?bf=fcm{+5A^n)N&%EJbc}7SHeD zSBzJ%^UuGcuC1)axn@a*!o?PaZA<4V&#;^9xZl)U{DFvKciUbM#}gt-mG!$#-mPB9 zKjUVKz&!CC74O)%m^0r`*3i6}?07CZ#AxOr`&hQ1k_ofE-Y6+4oHnggL6B1+Zq=ER z1%|sET>Um`&2gws&P>b*Husp<(X9P5>SKrU{1w8@ZZ*fwYxnIu^7%^>x8c9O&*JAN znE3Bu-DmBeem(ZpR@L7+y@h7xj}kuD8?Mti7dS&}&a=kcJNM5$exYQU_{{yrn{}UO zf0*K(cl`7|S-oQGThp#acBbeWJKu?$EWQ66@8i5%Z*p3;+Wi0V;Y+4x@y+=;ca1x| zy6qcJPfo}Ry*BCO(a#|w6ImtAJgiHk8l>L3r0`E#_iOR=D+~T=sb?;Ok?i?5peMwwL9; z-Tn3F4JL!7343l?mUQnd-nu#B%-nyQc4%xpFAwoCfI7ngr4?r2je z_~fy8q37LKdnPXb|ExboY|^&yv(91-(svkd3*Oznud;D?P#*GD+C;4Qs zm|P3*bAMcBSNOqH(cW-L$GMnq{6SvbN-cq`30^xdX!+V@7W9AERne6FWR3CboWEaQ zJ}&O|6*ZW5p~@(8(lhfp4(xZNSBbfY_g7W^s5_X-^V6^JZ`Yyq9w{^UG~BsY^l=#L zUf{11`q^B1TI9yv>(TWkE>}$VJXPySU+}Kza7pmOFh$8F=DQr&gXWyrGplCr!&z^m zE`EQMzW-}wxmETCpMz1=T+V%$_L0sJx%p~lhcDN^y)CnD z!anV2m-E_7ve&CM{?OXiz51iG_MJUJKJBlch5z~TWo2dwhbCwJOa4dpvwyA2tPw4~ zt9j0K9@o0K6LZepY;@N-F(+JVeyGS~pBS6jO(NaNXAaNZv(8LnNzS!uTiz#*+@Zf( z7oCuB>1OiVn3JYmrTU`0)8}9T_pk1c_v?LJ*4cAZFm*{}&U$OS{ilcMOitZj%c~e< z!&BnoE>HG&{6C}fB)`7@{o3z$m8woNT{!;VS7q`3jlWr)mNHf5REhQ)hqzDAGrQH- z?Yo9M>(ZlxZ+0E5xztb>^2wsYBemttQr|^e7oFc7*{8?0W}%Px^eTps6FE;3bNKF< zSFA9tU!Ku;YEtUqqClp7lMl?AoLzXyWXYsB13~kS`4i6+3Au9zt(%x>+-g&pwyiOFiB|7cFPxO1 zR@usuAtd6~p(dw4@3#KL)5l^{rC%mWmTh|J@L*PS-;8>-Lb;qH9s5qWZ{EHn*eyD^((AcjBk6z zzxuPFuq|(4-(2-iOmA;&ox4st>}c+>khSuWa}qj}J>5;Bg8Z$6&iCakxpuaiQCf>* z+2r^$6FrPvle2{bxYltePn^BL@KLvqo2L4^^#|A{ao+owmfQKr!SRujrKSIC^Aq8% z?-(BN{g*$=e@f8DYPO%sp=Zi$HwEh-PD!(w{@Cllx;|H-H?LJTax89YuoZNg#g+T^ z!9$s*FPg?zg_U(3&q#ey(d{%X=YPGHnK@RGdm)G6PBVp!<>{y2Kd_ZenSaVmzT`tj zx>EcEo760GqnR12-d?bjS;j9U!#C&VSF4>V)rAdVsZQJ0+Hn5ubea4^XyY^2$wgl; z)mN#`SN%9$MrH2B(~PT6UOXlca?+;Z5-nsWPq8j>cdYEnd zBBR@7e#7H@f4SQGGk4UiMLj1Sb>+LuFSYdCljW?GR`@w5Gwn-d*p+l4Td9kFLKpyDnXG+gAey z#lFvM&mERr**f9Qf!Hr>yKX46t#|P^=$}(@?!~dp4O(aBU3-04b<3Bel&cv`|33Tl zGVOTP)_rFC9Y)_4rFlL_%ddC+GyR?*^OyUD(X#4aX6D+z8fV5>%-b7iIe)r$&d-$% zn-ohb4W9AeWUCIS=V0r$pS^;4y-n$|)Qfo=mY?W(d34=;j^)b)1>N^}hZ-!uMy(#Y?wz)}2gwbd34T4^^po zNe^E6Y&df6Nto)}oXsmuzRgf&JUBH}ShX~C$`&te>uH@8tg=sv_%5kx)b_e|?2bGb z=fcYCb#Adrh_YxGXG^b2hguRxy=mE$Tw4x44~^T3H*VOhTVXJl@#wLc`iJLBOsWlT zxH><&dxdCeS5o&miT^)~#5g0I4NZHsjegHiK0RM(hGMvX$$5iL7N0fWCp9&fUzD_6 zP#%w#iQfoPU{c4xBK+l@ot{dA;MNfWgx^}Q)@(R|cXL8p!RNBcO>r%F@4gBAG)bonO z&)$S)Y3Tzx()jzwYGy-?_3a zW`8LyanFxlBU0wYRJE@+^5$q{VIC*OYV-q zzB1|J8D~m=`vrMT-u~>0_r0P`ft{CBiccQaeSCn`cyg=DF}Ck7wEJ#eO$~hdW@Ep~xscfrX9;h{1;=E(B>ZG-5jI7K4ai6Nq%KXNA`rnryA3l9^e*M;7?82Z;-W3XT~|{!lO+mCS9st*n95v`iZmCSIz(8bS-(MRJzoQiJN@` zgD3QDOZ7=B$!Ut{|FJ_O>R8^2`lQzx8yD!j_IVj*b-2$$EwW2`m%{e{&f9P5JXL*e z8u?dI`1Q92po%@CA0;Kfg6z=U!JaqD9=GpXn z^~m6!LoXF_|cpvNSQgH~^3a&u3d>@etD@%4}5 z8?)@G);n#j4Ve{-r!gcwx#8O{UgqYYejvh4b1rlJE{o$Fbsttet^Kj@?(&P*`ai5u zK7Os7uksnw-AR6CN97)7otzn|F#D0)mt*0bLFu+^uO4ag2s#~NT;RaBPVj-;v?m*< zdv-5tT=IAK(!TA<&1^oWN@s6m*f)`x_s+~q+XI+a{o4A~IxPOrf7^ZWM)uzpS){Ky z7}2#v#pq|ikGQb<{vSVn@OxP{*AzHUIU9V4>$PfyNcE#R%}V8bhi@{aE__&UP-^p$ z>`7+cb5CdO}W1)9v=I zasHyt+NE5)ddcOQg?C$XPAqT#b2IRrP^s=Y?OWUT-#h=XSX+IIyG{KEySYBRW^)xB z9*MH}W$8^ao0!(IE7Ww$t@%+uq6~A6zM0^%S?clP1){tGhvPrpdokri!Pa%ZJXhvGxwSY%$NLn<)TG` z`hVGd`Oa%6u3dOB@!wY6g{f{`le?;dxek53!p5O`+vUcQGPZd6`}LKPPx57+>`u+$ zo;IQO@Ur)fW^u;C2&cEtQwc6h)T}rpKIsB{Z z{gc}2e0`U*==E|VN1pIEx(se_byXk{;1$|ZfRg)fKc_;{nvDFKi%tClTq4k zXcX8SJ2!T*>zyg#{!^>%FD%;i@$GD;_Z#~1ziGVBw7j3tSN-SX&$loCGOf_*_>0!Dr|zF+T3)l-x8>@M-QUljm!JOQQ{SYZm>HAi z9)9v~6~lvz72bO}cYOUCwe%q4se)wpW_ACmFEyQOJ?6~|)PJ;BK=B~gP7l6QVJF^& zw?39wUjLvgD5ajGb2ravv55~2c9a+#ye!Fg&zG@ZGdc3bpVx19gcQ7(+d193dik>x z&s5)vnkq@J*0TCvv)&}8?NLhOe4mehj#L~DESr<^lOs7WVV={$nHyL)%PyHQH&(}o z*)UH@x6?^cyt(1R`h`4KV(#W@KPbtO=4O9U=-Vg3dE^wo%bA4C`nd^ppFcb! z%KKA_$(^qkNL-lr;Z#b$=hym0QcT__SHI#~<9Em)cIgxq3-(K={_Hk8FE3|T|F3dm z$FJq9pU*D)?WeHO?_X%!39H$?eI=g?;v0+SwDisN=AAR~oz&u1#-x{9*dBh?o3&9x zBJt4jnssMg#B!hU=nCcBvJyHnU36Mnh;7li2h-!$u>ap}*6!aQe=jcT{+(k%hw5|J z2;4d5btqTY^3L^XLV4MZ54M4*ix1!FsBUxiuU{A$zb*Pno92e4IrsB!F-$ua{5VqV z{OdR7FONJwwsGO!1vwh`d_uqf{Q0w(dy%Rb%QB|On;!En_)cL~5n1TVbUyWlO+Akl z`-ew`7h@bLH0LfY~2p-f-Cz%nU2ixpisd z@U)CR6$aBBnU;B5B&Xp5QcX-|RX~^m8h?WOWobW6<#^qB$@>93$91gbKJPQ}i zDKX&MbiSK$mld!0x|mEhHD0-i+hZHnyh=+iP>CaE{G#O$K$9QMs$ zm`tttHq@n;&latXKl=84e{=r%`TPEVy3yC-JEJFgcgd|a(sKjd57{nkI=NG%%jv+; zrOVZNT~$jzZhBZI`1N`H)oRu&XSb$Y*4zHkKGol_W8u~rO3Gi^nEZ8>SEi}>N;Y!Z z`Q^?(9hCW{RnwTwQ+dnAwBxP6er(|INDBUGd~Q;rt@p8`I-IUW$F5IiO`ec;EKu?1 zCr81BZ+<<^k-B}eWUs)lFMkiMn6Z@4AWz0GB>tU%kI;+s)`jhY#tr$M74(euNwxj6Bzcu$38c5}5e8sZWcdD+Ucw#sgM&l`H6 z^CZVp7k`Px6TJ<2qCJzMD_S2KeA?kz|E`JiNTu^PrkzJOU!0)dv_>MtWlQ6ddjUnK zUZ*ytF`SytIj7*>gxDXR`pk8gUr(mr6CYKW51zV5*3sB+> zy|V9~ptRsIN3Qh$k60gb345-;_+-wa7ZY};oPOP>UAysV%*Tesw*A)?_Hn%5^F8+c zJ$s$S`;Pg!pWu0VMw5T>g}fCzk}kYnBI4{DazVnSQGDOOwy6(x-ENoqQpsD<-B#3| z5TiabkuBwbi#gxL`Y)cG-b$17m>fjJj>RPWP@mb6Xb9Y{!AANDwnMEp# zP8Vlf?OJi#$|thYyIAza>yL7Zk;$`8e{Ejfe{fsZ%f@KE#FUta-@4CBs=U|f)O-}h zUU;}8Tv_ti5tRjwUV-0>I}LU;K6dq2+jyqBcWu*b^PAR2k3HDz+!N~=T2)e%_G)Lu z>UBk5e_<)I*UiLxT9U1?4)c!FU2`Vqs(zhzBq5V0IdEF_QN}9nSu)XviJe>Sx;F{# zTuEO6@Ft@+k#Z;Q-@PhUit zly<)IzZJwQ_UN#J#xut)>2@>D*PnYb-?O+=)cCAlV6@1>9E}`3B@;)H#jG)+kG*6Q z9w{lriez)VmDuFRTzRTj@3HBL|2c2`81^u{F9?xwQ?ZxgIH4%%ov->p;}P5P6RHbW z+ZZdbol~6Cv+_V1$5SJ_<~Q}TdN>~T@YFpibN=?qu_35q!emXiiu9!Y&5V7Fob_)! z*u^It*{*hPQ!;}{{yWb{J;^B|DHr%Fb{EvzO!~&R=Yi*fkmCy+*7w{@7rSt~q~)dJ zn#nz?axRK?2HV_@GdvFD67=A>^p-8V?~0AMk!|=Eo3h#;E&@JJJF~P3C3@d!>@7L4 zis`q@i<9R%;^O*xUNqg8dvN#A#-xU<7+InEu;jD$_xA1+)VaJ)$&jyLzxtn4wPm`6 z7wiJ$Lm7p?RB7>OX#VrCm6#f(6DqZT`$^e_!8~Frr=zsFFK!N`IQDs?M=e6nN9{3{IXr#`*e(IBsJtKCN}M>OY?CBJkCuRznEFM9;8hjh$uGSAPP z#nEE;LRH&dEuh`h!D-><_kG&Q`X^+rPky{8O{TK`Jag5t8z$Tmeu_WO$nQ=t zS>mUukle3SdTgRownxL?`<_P|d+xWk^`GGAp7+hm?M75o)aAbk8|!%*l`!QSp7UNsCwQ-vpC`(<^5ciQMY@a`n|~ABipNPab?^ zq^!HW@kX_};aUqV%-GU`}ZAY+v@P_pI!G*>Bp9``Hy5yd|Ga`{yvLSS<6#r zmzHJOhwKh#9`d}VzQ+FT=VEUKud|(-HD$9m>LjzaJYZxkVPZenB62XfH0$TzV}FD0 zUeqzSUK^NuNBrDbiM(u{zm=UQv?teZ+SGabPF+`6{ODX`6wRtuy~sX)~|nz2=7; z;?70M9FAGjviWJz^?WgA-iDN&%K}#Z>pQ=5LjGczgl7+eL_Y^CJllFk;OG(7ZC>+A zgzD$5)6So0*J`8c8D!$}usEdu%G?Ql8w+e((@ylRTDY0rxpdwP|12?m9$%)Cxi@;` zO6ITN%BkS|f7fzhbN$97Cffp6g(ZF7Hu2>m2@wwY(jC{{i})VaRpq>R?90q;PYP~k zS*A^Hzdlepd@I0; z>)nKV{1N*uHf)$!#FAm%HZkDe$>PX=1IykQNNSdH>)8^E{r*kKH ze)Nubb#!x6EO&ixbKt~)R_`>MZ-*SL&YW`;*_bdR-Dc0^%$_G3-kqt4opIyU)$gaX zPhXk7qeC-2Z=>i%Grb#E!xKAqUMOPFiAZ1&@hym0rdZc-dvn~%C8?4+agL4uCM)=_ zk&xx|XsmCP-m#fySxi_u>yF~64`)s!tl`or=@s6xtkdR>;W>5x`oyF=K_@zPryI;j zt%{VYudVpMqhz)BX{K`;Yl3-KeZSCFPvYQ!g}&>$K5l1FBUDFv-F|B`qgaC;jrLB1&9vGH*uK4*$DNDbz$L=j#%zSL-niV;P-V;rmoBXX}=5GwN z$UncYW$4Zq2LZ|2JN{ z<;bM4q9m+7J#BvRKDirAjshGkOocbAV|}b9FMIP*BYd8Y`gCh6z8PEl&Q!7OQ{9-J zqHMcrvuv}izz(ZL|1GXEyMA!J`{4eeqdZqv$UY69(GgME68?s1d%%lt+^p|51iXl= z<4=*znyI0YtTKUrMfhxEyHk>d$DG1Vw0@gJ$C?|h?u^XnsXyX+rO^2FqywHU$v)F` z!rdi|j~?&ve#ZQ9(@trXjrw|3H!tc3&GK(O*ca3*?bXT8b|&)FHPuB*!W;`l>8lYXCC$sb&C!&cDH-_ZEviHFOqpBM{ocZ=7Za-g)Imou3^=*0Bn z9)?R-9W!U0P;kS(urIQ{bBf0tHmzkZ7v4DVg6ZCaoGh;iKR>&$R|>Gz7)LHon{%v7 zr0v*^3og%7Pek0R-|=CdT+fbo%T85$_5a!xT3g+``QrNT#q0_f*!@3nKh2ugwYSL0 zHM#fCyI&!j?Tqr5pVc+wo$fE-)c5$l!N0HNB}MbMo=VJ)H0jdOE;P^Idaqu^$1*(3 ziScvjk3)waoS1mEIzVXUot<{sPZE3g{`qm%@uK~q9Og2$(+?|E-b^^`y}8up{;7|; z=hRC1!UV2dS*GoC;+B_XsoH82pZnGubq_0L?EWKH>Gd*jHTNz#arwCCe?!@B3ZGf( z<`%tFJ@mA@<`PFut}AKBTUEcDFgqlDtDb#pyrpR2twYYSui_t1y|epY@E)Zfahq;< z=r-)mDr-6T_PqYL3%kEMb+6Sju@{`_I;-JIsYjaklew9;d}m4)9jzAF%f|i8 zr*BPrG{cASWq=58T8GS+qnn#GeuY*?`js93_eexV+tjRN&uW2%EQ+dGdV)8+1>w8y9dDhP?7BYJEP%rvmgpvDqHovMW z%g|RJRUSC=m-`yqINZE*EiGZ5&;gc>QlT?ntoWKGb^4EixY#e_(`Pj8*yrXX^)~XA zUyNH=ut8acPdeHxu(MO*B{pGJylT1P#(pGTIup~^PDpha#T$%mHemN`s zDtR+Gs{X|)p3q0VzZ56x1Xb>@Js#fgnigvE#7xp*%@-~CYko_cmSo8;kM1~a?HefS z{d~)r%?$taYYI;HTuf^CefRNfTdR6${o}7}PjR#VWMSG9)nB_wy~xCF`Qq)GZ+yNL zW^M_4Ghcqbz3!sPi4zZ<=zenX)9=K2)m)$S8cY1;m!}Ia`)Z}o(RN1sV6H*Ax0*l4 zDa}mAsAYw}F7M#|6ReOl`@_k|Nh)WALrN#M2xzLz^KI8q@~z;w7WMK%e$v;(|DS%m ztiK#{-r06uL!DoCN7JbNq_aC5-|cbG#H>EdKO1RT*zy^zg*3#WUyhb1Uq0KQ5R* z<-_gA$M?S~&AdI+CI05QdAYaG$=R{~QR55W;K2H4qvX?@Gy8VWXsKUqzFjTsOS+%S zU9(mB&OsruOx6FtuKNG$<@2LQHeXydE9<&WWMTk^8w1hV`=jilmt)mZtP<^YczX@dHoO5&zJp9Z%mma!d0P`^ttQ(x!S2KZ>gNUa>O^H zKcxGn*9u$Kv!y;Zb8oXhHC0|HRy99cB=5Y#g?-`^ADI7qRdH0V`>A*#&j-<#e}ScE zqo)UG#QArwO6t;KlE`6Em)x#!?vP9h$G4+llczhL>vX=Uef+?Yy9o^L2ZgLYepR_q z-?@oz28-9`um!eu>SsUK*hc^1jo8<1ANh?(kG*BiVvhX|T-@x_Z`*Aa)3!Jpd2S=~ zoBHN8kq;iZp14=>DQD8gn|T|6PxpfayMe%4Wkyi1>cb-q)+su1tG&0>$5 z!<$=?f-7@dc*M;NZbo!@XR#>>tqe@D7o2%P`K_Ny+3g!AH5O}rPO0whiGR|1@=@>P zs#TK~b1gOHyceD{W6G-QOT-oY4#sY&n=Z|N_|3s9hxyB-oaRpwdU&KH$j)mW`w|Pm z|DK8m6y-_^6ze%yI6A|=W$nFMus~_UN6U+c5;fS_bWYB;>d-%#@aD;;?N$3%o6a-d zF1b)+X{7FTwl-JgV(w4d_`SL`!k(Tzp1eSA=@W~aqMA3`!d+jAZ@+wc-jt4nyg8Cf zFQv|Co@@MJtK6!Xl^@ofZtu)H&snVSbniniX8q$o zq)ziU%-gW@z4vrKhmJZ8P48*@yqe`_C+5#v%(;)xRq21j+i+b2#%I$Vv(H&+rhd{5 zvpDeES#xz+p}ST7Ci046Gq-GdPUckcJKt<_?_x>@7Tu6 zI)$~%Vvo6XK2X}1wB%!ZRfHAKhECRMa?hS7dGhBXhaGgp09`dO`}q1lz6du--B$FFyVk8D0_Bs~$s6GuP8=#x8a@46IMA>Uyj;{h;+bvoBKak?F5?+8ha* zDSbV()bz}^XaCY$!u#(2EAQB3wfuRX*xNJ?72~hh+Pn5yKRdnc-p5NmLQZeyZM2Z_LnAlS!k$C)=08a<i-Nb{yP=% z=FrCZ0dFd+|Amw`CowLPeqSVVb|Yyi z#29@onsY4K>Ac9qlKF-8ul=8WeR%uu<{##X&TzN0<*{KcoGUj+Usu3%)M`3_&UzJ9r|Mb$+b+cgDo`|YYM$<&{Pti zz}70;Z$I(dv~^d7j@P@_d6iE)*ZHL>LeAw$^M3B|`y4Y_EhcY%^e+Yq9^ap-qcDhkBZLgSyWVQMZ!y)ABx?GvZ%Y&n3~?wch-6 zrE9EkZFeHWF7FD%o+InI*b@&Z+|NY49tmoEdoI+(D(;hn8 zzvA!VV^BKj<*4dlBim^`V`WJR_ojw2shAZW@jkLsUa@aId_-5uI_u6IbNuk4uoeM$XCo+WpfZuIqcoXdG^@#g2(&Fhykhpl(ga@o(Z z+?H2u@@DS~_td)A9ZB$9nrg%86zZ;8EFryoZj|+d57MsHwLd<6>OacD7p&biSLR7% zO!X=2w?}feKCQBwA&|<*w2AHZ%jVXpM}m`ju9v-9VxA)^*e#oH?eperkV;SE ztpD#gxqG`N3wxXT6Uwv{E{#|mgYVL8Ln0r0PxVXYdL) zd889{U~V95n`y@ve)4^`RL&gkkG5wYOm=aXnxn;D z#52=O;Ps@5u3f7qOgsMLb!GR(hK*k@y`Nhs`m=WOCo$cQ^Ak0eZC2SC+?BEV$67(g z#Z3_!v!*kt#a`w(EkBHJ93fSB7Z?{?;l>@ z*4j!7-`&jQ%YMB6@_{S!WLE7J$_SYBdQw-%HOJ{i_sz{zY}Gu!7azXF^reCQbC=$+ z%uSp;MaG;_tv2j=>A!dn?G$RC*l_s6;wQGZrd7#5(G%|VH-B-uR!+AeSkXVwv08F{ zL&E=Qf^loM38w``N@XfM)Tm%n6<^|#uzSTHe}-*0ynkmnTL-+!srL#p3SCn6Xh)j& zvc)Y2tJ}3*(oN)Drygf(x*#6juI3vwyR%NrRa5Jp^NQz6b6j+HW%=E_Qg>>RNbtMP zvgyy>%$ni;>g3^NJ&C&{W)y0Mt(>8?w%z9uoAs<2yL>W}&X|2kZM zrll23;|=}ND$=Fnw!wAB;!M^0^ysr}Njuw<&PrtcZrNi^O!uD>1Qt z^RY9@Ykl0cuO-r7?g}VvP)@0dRSGx!a>gr#Dcj)w$pk~kCYc+rn9e4v?p>9Ww`E4* z8=EN^4HGn0s&^I(g^Qj^p6+WKy^HazqJgTXX)>`UUSKly%fN4)=BGPKy;i$q3>T-2Hlx^+BHUg zv)ZXu2U71Gy7KK#pGubYyM5-zQ;$B5WjC2~G;+g(+y2|kZC}fXT%DpSH#Ki^(VY^x zhs?fb-6XfvAK80MPI%73hzasNEDxuAOMLEJ=^w6JDOWXZ$;WFidtR5M7b;B@_LwKS z;$rlwYK>>v{YBSbe*3p)?UXf=$F+{9d@Zv5qp#H3*Uv9^y7$LBE!NK|(G#R^hcDH( zvC>hEnB(+YM`gZn@Rkg|z{1@sSIyV6UE^IYyE|azCW9BV-kzyXn>q397ORfG$*I;x zJw_$VPKT{E_gZUGaoZ=ys7PTOS7XNUbJ2DAcba|~&*p12st9@bLwaM&#}kaZYBxR1 z7hYSO_@QoH&>L~7##S@gpJz7x^x?6BUQxjH3HL6cGrGYYevW@PY(7xAVF5!*{6wuL2U(A;C-UFDU0?g| zH=~)?oQ*O6+^WKF-9P(C-@{d>>tE85?|Z90mT&%X`fu{>##ORQe|!=5iV)gzIo>6Y ztAG3c*+=8gZ7jH(QMzdVrgpzSf8V^9yhrrv_njh2a&8P1_`0erf?dK2vbE+@x zXONqd9R9Vwv;mvok zui_UlTxz))>^IRStL%)lrRV{f4y&4DE~Q0lU(UO@S3jAB|Lq}f^6b+Gb|y*?7@jlRFL% z&Z{;08ui|}5tIApK)CJK*JZVSFQ!WN&DuWqw=OedB){6lRAKpqTRSC%SDxDKbZpN* zp8T$7=@Wb|#__uyn*R8&u;KyT&ABJrmOR#<`@nt9p3vQo7F-fgJ$OmPIB>!j-_0W5 zHyB^P_3v_h!iPx-%X_t+v_3tD;&jHqOG!Tci$1jd_B4*Zjupsv{>UlnY7&ttw;UzC9G5sPix_s=V z#QK9y)g~4WpV-hO=gQ0JE|#}<@yW_goH(_6`Jt23w2hO+vNjexEZ7#T!9B5Uk3eF* z2KS!oz5o9GI%t2lK91$BQjgEWMom*y&FycF{GPN{^G0;xTc1a}?e^$NOt4As|JvRx z(Uo#-*KU`OIhg^e%eYjEbkl6!@`|u7<}MV?Ty}4(@E*Po*BhIfbnN@f{-i#5IML?! z2?2f9EvbzUDyA-sXI&n*cly@}X;F7PqjpaIIHO)Ug)vfODc{lRl{N|=RG#kbUdPV0 z+(V?orr>43#-MJ8d5d;ltmDv5%W?I%+4EL{&wb{%t$*I9oU#wv-7EDpWsh|k zS37n7_s0{=gDy$_nSUtFKazX@t$+LeetP)t_wCb78$4AC)vUX`iv8yIFKZ|iC^~sj zV4jtfl0%AB`bq7I=MxuMPE=}(5if6EY%nkJuim;#>7Ng2^QP8caA;xgpQLIt!%HdF z^3;=i&6&@_8V@iZH-BbzZc^LprxMni`MqP$?Rgqg5VK79mG+(TTS0wB!4o>;FZpyo zy5f22@we226OYy%)8~BRWnuU{?%tEO#HIrdpEjgMtQMSA_3iUT35UPy51I2GJhsN! z!RglP&3=m645#d5G|l&ww3t5AGSM$DTDRqnj$&gVPZG<}s$uyTCol2E*O zc!i~q6YGT~5v{Hs0-Ad-I?a=_|37)|j~(^OvFA+-S((HhzHR1XIsS4&&p|=PS>ex; z|5R=YR%6|^Eb8^Lj<55Q!uI^Di>URGm)loU`}_L;zx}V~&W@g)^*51Uj4M&mvy(I0 z{*%f7_*D=8uf1)*WbwmS&mSyGe6wUykK>MeoN@Z;4oCiO4YHbb;O2d{w*Jd3hJ0JD zC9Ti!39qltmwz2T@7wL$uazWh`;=bh2h85TVuEvQT-B~ky_{aET@vR49G}%rxsVw+ zWv%#|wH^~2E0c3ol3u3YsPqfhJoirUXYac!eJw8AJOgK)ndgxB;ZR+=SJvd~Z8`gc zESbgc)umgMPi1Z~RP4((dtx{-ZL*WcYT=(hoDD8^ZFT%m|53Z-UHz{34inBC&5shV z-UeNeH8`&vaewuvZ!8tpvKQ;d_#5L#lAFI|2x05&9_;wZ%mr@{OUBZjk7Dl)8=ka zTe>0BBSMAmv;N&ueqI&fgVm9c?n&RRs zQ!*NUbSv*kwS3uMG9mhn$gz}-+tp0UUV_z*2*$7sqUpBjpoZ%Y+!q&bo^c5 z;j;%dK23S1lC{ceV$upDw+|tqLS62uY4vZknRg$plZ;f0a}_C!vHo!6WXV;@b1G}J zZv_jjKex^4e)^+>;inz1UQPuY!Yj{iSCKK;$KWqF^#gG+l^S4gZm zKgr0eMZ`sdH5Pm)o^>-)J2^jW`4UrlOtbp0@E%TI@vgfs4n?k>j!yjwW=c_z7(nMYS_ ztFhUAcLqzr(yOc0eWqrFrQY>$K2SU5f1`WZ($hzTHm@%g&)kvnSMzmB0dp9@w?}tyN z>%zW?-_5`Nuet2xq8*1H?X$?AdDS=eO7HAzXM1PIE_x+x+Bzw%aGAS$&hm7>IE3W%ZSFZTz=C?oe*z0ofdIpxt ztdq-BJ>EpUyw05d;Q#Y`XT1`b)90I&t+LRM<9KmR_s@*!XAW3v9_am?-oI(qJG)b6 zmU#xT8c&=TD!AuOZjb!6cG7y$84C3k?EU&T;_p}Ox2yfXZ4UR>?|=EC)E%I9?7bIHG z2yhbr*A;xljlEMe|XP%`Ib)!;qg}I*IeXd zRybB%SfrV|JRm*lvQ0NJ?OD>e|$!y){e9Yf?8u z<7+#^qc8Ov9IaTV+r~L<>v6t&wV5$$Qb@u3XU%$x$}gW6Su_eKUm%akg&CmJVu-a5oq_|L4!JkqSr;AmSs^#T9Irf(b11^G_LQoqe^r&OW#DY)q)#-Me3R?oWET#MS&$kd5k;ReP4ryv|y+|IdxpTR-ix z>fSN^>N^LynU<%X?yT=cDXe|+pBqpg)miF>A!P%l&J#GVRw&yBW~ zQZ?(CxTNhq@?1#%vEIwYuw;8mq4f{Gk1>;y9*eH%KDL@k$A7_BhAqht&TCmGmn9Z$ zW471xINQJBUCuUcY0jpFVhmGF*gx^EG+D8s_v*cgCJHASWly|eR{DIwXY=HJ9hMpD zZ#~`w)CV8!-EukgiO7`K3j3s%t6wzXwYgg&EqbHUM!v>o2Gh*TDe2)Mv!kAvugZTm zcM9v<3rwpy=Q%j>SM0fS+_RUDMdN7Q*@a07p4>|wwB5Ij>9f^hZwP!5 z;Jf$m7kA&Achy!u)-J8zAyYktC;sWxCLWcm6*t!#emOp$*ZSTn+3L+t|9txJ z&V@GbYd$Rs&$2vyabtM(<+sUu&-rhYDvD<*Q~c>*zGSb%@tdEMRTy~o8k>IDeCE3E z(`1D!G9F3AD$0SrtJeMOi{)}X@A*#6zHd>LggE1Gz9(9IAstUzQtYyRC)V3#9d@X; zTeJKp<3~Qd45jSAWbu1$dnAv$Ff>l!QohIN#Sk62-GA5ju1Paz3QnrK^pv6VyMk|H z&2}T@`oBg0za`eZw70MS@#90y(%^$NI_!s)&+g-zI{8$ffScRO1(Oag;0#~4N&MjV zvn?|waMpg`_22NDb-(@p*UwrP-ZHMssDIr4n!DKOiKGVi{_ltU`R(`btq%Pqa%az~ zX|MPHUbWu4QL&xo@In0Nh4Lz5y+4EITx@mV`ub_ec z`L?qYm-H-d49+UOZow$q{;~O6;xD%&jRwz4COMufz4Pe?=f%0wtba0N_QaRValT}5 zas2STKB}i(via%0f6gpUM)l=O8IJV4{*)eJpeeWb<$@_DlOuMY%L$$RH`VGA^Fyue zE=qGwO7$-@Q8PX7(?>c6>TK%f=U8l<)UWE}!l=_0|M*7M@r~sY`6BH~L9SEdI#%?R3!ThLsqi^f zdyi$l@(=Tg$)6fDr`K~9Gp~C6G_^maCTv~lg4OdybWen6ALV;^{_E-HQ%7v4RKK`> z(MQ|&!^})} z&VG30yZ-z7>rW;B?I_NiSaLq?uz+`ZN1l&%-kf{EXXmXlnRw@FkZP#%+_JxO%Y;&` z&#qDs>t;+4vXz*wHM#!<$5NfcqQ#S9>RG1ir<`|O)OlIW=GL#e)Rz0-bqqqzxTI_> zn3bN&VG_G?!{oCzM($DiPrY+47fp=wsq8EH(feGYKK^2Mxt^o2+TW*smhyWU?s~ku z(diR$My;~t-rq3YW%uK|7u{RQck0i>T^9A<_J__*HGFWS@^(_Jex2Q)bGy#fyBKRe zUw*cp-Twcqpho*kJ=0jzneO@DzWRInrDTJs?;*_<=uOl_*`wvBW7r_0yxiJ!M#|Nir+{rm48VX``T zo}iSg+dob2b@(3ee74wT(MOACT~3YV49paIU*U4|?wVQCuOI(kRav*Y ze%H=3sk4)xt3LEdQm=n;Sl1x(me~y;J`3&U*4+kBx`D9z9ZMc@x2CuK)SRAI@Wovh(dv zRqbT1d2=K0%=VT`&(2)V-jLBGTYV?fZllrCdv_FXzZXw@`}Frgr8DbGQtJ1ng#B1k z^4R1}nBcLjxQK4XL?4IQ$Ag;WRMT#0)tesQvGz&%39snO#aC~7mi_zo_21*ipPwH! zmC;=>lkwT{WBo_%#A+TnndPgt%z2`CJaylut9LxR%`z1o8NS^u+Vl5yrr}w+;~ibs zWqe<(Fu5`}g8yUR%9AxI;@7N$&g4`{*Qf1&+`f5wNo{(8lkot-Qio$YlWmq~N%UHb9X!{h6|ynTDv z|Ni`Wa$;pCT4P^xZZz)9jei#W)Z^?U*CR?3v#svCC$3nU^zl_;!)5n_7uWmm=D20# zDIDfszo+bp!qyLEn@(l#VbprIK4w+i`~_>{v!0&V<82>wUjE*{uceJ=T|%7YRLkeB zcUE>c53*rgoHT3qSKU2-F5P*lud`oP+C5pLC);6@_bt_|*))w5Qu3^6ErU9;2j zuf(>SyOz!F|6#v>{~p`=nBT?BZ+grY9hGUkDR4x${8HwDe=57P-s~-Wm(MRR_%ZfC zpV89%7pq;q2{KRT?CB8kZ8f;CrEgn`Tl$G**{9boNeDl8_c7b$Af0>LrygtUywI=q zGCE<)Y1bsLe?{rH7rk?hsXil|R$Rg}IdR^T)}@FdIcZ?oKV zZlrM>R@!@|*Q$;PX{Z=-`6d$fsFTo=*1IBq;QlRkYE0Wk!0N zCj;vR+cg1Fjd6WbyjEniUsx#fe(o#AdJzk@IqwTHS)R>csnzz^)Kd>r7F{pVu#jn0 z=5?_sQ9hybk4`2Vd^b97v;XDAtl6UPR2EqWTz9|ZBGSJoFEP+zix

ODjZ~=Jhz5 z$1LJ1THUT8Zy35{GTX|cl%08M-wR)-R{UB2ROFcV!F`MM4aIY39o%?2`CrquP1~Ca zE^My<|NHQ5{q_3y?f-AGsN555FLEMEJLdnzyaw;@8OGbYd%p6=CW{&gZ)1~PTT{Md z@9c6R7QdMsR?GHeM%V_h*5tgMn63X})7cf zCNS-}k!Gdh;{8V5Ik6*0bjzXXQEQ)j^~ahTCQMxBQ=cWP|7v-DamL39KF4ft34Y@K(!L`2 z!|OAL+fQ?HbRYiiUcc+Ov0(4Qq?&raBX<%w^ZVp|rli~LK2j~LSo>lvi+A0f8f6}K zhLr~ccDL?ORBylJV=^%%THDcWQh?|J4_S-z%GJ^D_||H_ymjnfPNnn;gY4Xv8av6Z zWi>DK7WI}XZmQB1ao&>V(t1Q@_lgKpb07cODAvgw7LM22%1_?k_^1BZ%VR$hn>HP3 znY^E`a7N0u11w)o&f1>8So&^ty4u;+-#0%CmptuR8UHHI!8t2GUuT!=!@X%*J5}5S z3mOhSIij`uak0%u%X>MQ@yBmI_+Jy9eeK+;ts9jX1ZG7%^J&u6iGH0lebF`6srlJ4 zfxp(zD0i%g*IjKtQ!&?9V7JiEXZ34CS^3WAgnp`gc0VCkYespp%I!;1S7z=Lym4@Y zDdUlh-jl{}J?18BHFk<0K>8)Yb|5Vj|n;&_Y%)ZRxVPSXjtKs3j z=Eu@Zbsck5o(Wj|I@ES{pWLtO&exfj2rcw`QBgH>L$5beW@GqE>%LH?%O`|FgO-&< z)-=ti@W1f#Xsz6e(8NtLJnOH|KJ5{5fBErn-zD|-HjO{`PnlG(=~+^W>did|FLT#z z(3r+F>x`jGqT;Q}*hW$Rc{N$LXDcqOjEoDM7P%pMo{8Z4Qri$MtBai+MV!w1z4k}t zdQZhDFwQje;hK8(8n>z{mN3cUK@rZ4aJnDF}%Z>}!+s8YZ9<<38EpI)|?i@PspKQDQu{oXx$ z_tr#y+1a&-t$5d(yCS^t3ePT{5y;##^+$5}&OV>(Yu8xTzUUH~Io&hnP(X2Sya!*i zYr?OFk8_Ld&i&0`ycf4mZ{0cL+4EXAuP*-kq%ZJeh=tuie!blH6$X>?YCi3~bm%L?e--;~w}|;?^tN{gM@fiuVe{_6Xo@h zJGN-}Y^+pfX)bxrceZQRvf%vaNxVj@m#zxZxXjx&*CbJ1$IQgQCn2Ktg!k#}eG(DZ zW49f9+0fsntiNs7!TZ7{5sTL_96Kpq;s1Nr(k&bx6r2_buMPh@ZSwraNq>46)wb>R zXqU43xZp!cs+K~ih#%)mvnd(iMwjv}wKTp{AmX^b z$!Wg%3OipFEBhd6+j4FNshA0F8z+8RDID_t_^Z_Xi5$m%ZuoMuYO~1xI{P?z``WmI zTNnKUR+iPTy3bhfsAoaUid|O6ZI8727jG=K%(B?7{3OdVx!ZQqIz1sSFNxoO=05Wc zFp{u04hcT)U%B^&i@DxstL&v&<(ZLX%NE?%ezVp};7j|{sdvPeG3wYXuRJ1qrTp~n zOSR#iUZ3;&|GS<2_kek}eZ&3GXGdL9ZEor?3qOxa*;{e8roM5ht*Pex&fjyzI^@qM z#m=*q@(jP>Js@aWXgGHbx6p7Ar) zJi6Ff?p!4rwsCoq`(&E~cg?vri|x>hW_qW0sl6w~KU6aC;g`9e*HliLAkfD#?S%lh zB3DA}8|^;(#}Cik@bfdX|6cJix$Q$e)0&j0)u-e3Ne3Q2YczZR7tvPDb(bbx(rR6K z$L^Z8)a9@`qnQ6o)`=eFH}8+l6u)m*^XIzo0^{}FsX5Mf8kVfcoGv#rcJ8}Xb8a0g zJbLY0!l_*v=R{X+=gU15jv7p>IUbfWm@oK3lx z`%9zim&@P&6wMXBzcK6xbu#DUMisza>7zl`NFxI+9zf%+QTtXh~rk4 zckYg?l(thc>OVQIT6A5MHa}?o?5cQb&S%?69kz*1I%S5&6@6Mip42V;+&Zt$V5`xm zeJ^Zv;tO6Ve%M`@@Nh2kIc?Ac`CL~y`N4J3>CHjO15@0OUCi2E;QwgeH9^<5?!Ei2zn?F@+EO6* z^}RFIsSCC(KHd1axPI~0mG7mDp8Q_ne6;88gwP(B=|+Y<$LB78b@AErv->WGu4MRO z&h}32k=U9h){tSxi0{)N#$!=sQ=D!mTe!vD=r{+nian>v4&DSP#3UA8$%==XKXM!_Uuo z<6IWr44SLfP-`qw$G=JVsM6imc^{ zGmXn4IX_QxnA4bRmY>Ey@j)UlLz=Vu-N~Gsp#}v9efc?Zm(9!7=cG;q2Q$h$*xsX_N<-=DEdRf==2F<(3DYj)%o3quR%-dnG4Mr@w$D8?vK ze@iqq@Ar-6dIdi>J10F~!Wt}|y!N#H?5%w+7vuVwtj!;A%rkG^SH`1l;pDr+^ZtqA z?uBdoW^2peR62WpdRoS_TvyTWpPALTCtiulMvtQn-zRy$+{8D_ zKH1{t`s(0kxoqE_DE^-JSGIoI+mM>2>f%j4QZDr~)GWEaaZR4mI)9Vh8LpInwfhR^ zpWdDGDdckqQ)y6XLG04h2T`q#Jxf#^rmwY2O-pM2XsJ5yb_!4Wv3GxFr)|1_&)2T) z>2{$N^Op9itbB)47YyJ`QoMNI!SeB&O_6$ zIOIQb5TEjD^+7pq*>%ghCY$`5)uE&G%J#3!`hEH4T5sQe{r7YBw&yxbN-r%65Ad`q zzRPf#UcB_F=TgzIsKljH<1#aYG9LzIp4?<$7vbi%d#={nIIXqwJL;D|747;nPmq7= zeJfGMB9$X=CM;Ph^|{eVr(?Fy-Qfy&t`>9#L`D|tQ3W1Y9&av!MX6dLrdteEh`S*DX%%$|} zJ9avT2sXGlo=i)gE&eoBYgeO}MUZ;XzKRLU?5jA#tD?&V4$7t{WoD`^nfBb_$fEe{LW>VAJ#J$0>UsTway|DQ8W$fr>aD(cgfsE}m7E_E zUA^5dMQOcVeZqSqrOnUxxb~F&{F~4zeXGv!w&9Fz0(p{;3%F0Ma`pLSv{+zHvZ_&s z?XnA*%b&O(kT^WEOk~^4*jo&?nk7Y(IGN^2WLQ33BO$j$rr(TNb$!C;XG@k&p5<%$ zv)S(Yl7#tu^_*t$9dphG3hS{iE1ji!ET`H)qu8cmVTWT^+q3SI{|ke~U+N|-UHa$K z-{t)FXaDZ3zq27R$NL#uL(CM(zkRdqzWKU{*O(n|aB`U%V`Cc2r<0O)(Rl7dW3?B3 zx}p;t?r*PFajlB({dT-5i*>2_%W$8Wj(Re?B9$if%-Hc>e|A03oJWn+b*2XHVjSX5Hy>lX?UGy7q6M{`xPEH~Ud%Sznb!Z-RaKHhHOTVw#iNY3;I9f3~#S zWT9s_PHy{Fo2>lQ_}(1P`jSW+CBf^Qj7xf#_;MWEpOe=ipd96EC)`lhA1vy2>8jVQ zoi8;6cNl%sS>uvt^02>uz5Mzx)yoQOs<|tFw$EzbZ*}o+a%)(o=|*FoTdVda?7K1T z6wlGV-rSuPJ6HaF;+Oute%(~hSk-kuLmIbjoqw%x{rAt4ci7CiDQs7Q z+C6(#P5xf~DeU~cub+S0zZ5=a+xk^@^ShLrr&oNQS>|>5T-L45v%k!C3V)MZ|MrX( z%j%D}tdAB?f7#lepk;3ubLfhuXu%IV9-i>}FK)Yg?q;s4{OV?NxBmCHhtHS4&*z?S z^+sZOaq1)!riDs#GLoe()b($6#)Bnc?y5`0rQk!mSqwi5!qOT`gJKa4C|zgd@Ev|9&QCTlP!W z7Kv#6pY;j1<}mu{h)4zOfBE*?%DbF5O(bF#^E~RcpWhZVhJ`36+wt6#*jmK^g6WQxuL|?`=aeV$^Hb*OVLH#xEe{bLZ`}x`HwA0R4 zC+ELcnU{C}&+YHakFPhEUj95dj*X133bGAOl^2ai(vN?epTC)WO8qZv3QHk32Z|<|dFP}awow!wa zS3~G>AJ^36vqkS5`Sn>Jmz}CU%J*TO*pZ%{b!;=4v)`30QWH}njV$Y_kcK-Wf^)l-d z^|`JvG;O*j-Eqz>y(}y)@5qTi9=$zHQ;w|QHQ4y_(PGi|FvjT%b=e9;|Ls1kWBhrs zP}i5s>n3rp52*9K=@K^k?03U^pJp9YOAs)%f6m5MRu`l7@UyIl?7{DMtA#bB1$qiY zwn|rIH>k?&s(AH7gI!o%dio;^^ClQl*U z*)R0XOsemeyJhmWSbVCsQp~0xzqQUE<`{Z-@5pJtA}iQYvoNQtH|*8t)eS}+dZNpW z*q_~7{m`cKmC1#)d}$uhsP2i^-W=G#{dE>whuUeMn7rvHCBlndxXl*f6VNDl*5Ua2 zm5qi;x;~%IOmmMYjjPW*TQdJny%77!wa}(DPCh+VV#bvEhuO}xixXXEzW6--_wnV~ z+!G5+rfM@A=(6uz>e;OBEPnNZ_PmozwDQ^i-`^zZ7E&H72_+hP!WG{Q#tsi0i zle3j8#LU?Cc^^$%nNaWc`McFq!Rc!JHU9c`Mu)n09BJgxYU^tBKg+`+Jga;9gl**_ z0{4XVn^GMeI#hGcJ-2boVT|6To;f3%G4T8jB~`}ahN$Y-eSE!VEd#5sM;R+#;jM8I z5PAB&$j>wO06~M7uI)*W)YS6jn>K)MiyLE?%s@Qd}taWXaMCJdO34p6Ay{=V}|Q zJkGSHz~|v3-p^cpC6`XFOEGG+lHPr2>p9C0f(0KPg34dN=D)^wFCqGsfQYYyg!`Yg zl-pW$rTcfTe)jFtpO;Tx{^JU64p0xv5;^yM&KV=yt`0@h6|?VAho;+v4Lz~&dARWVfOj%6`vq4FET+xAalu+t3S?u{oKlXf6nx@WY$gf zIo7Mb_Lh5fRlI(&WKpL?^TgUOZ*Eu19=hAq&%F5EpLu(QE=*&~{j$wg0@)doubL`s_W(T}7 z=hJVSeRipq+HCbd+v9rW?e6Wb`}H!_@#6$ux3>DKQ}ZV8-Sd%4b@gtWi*J(i`5u_b zx18=)zsxEi*YmZY?SQib`wNeG-*cXNeo51_<&NZUdggtFp^4|;8}qYzOIMrBh;C%q zvhwxm<9@c&lAJeW-|{#Yw^()QpTa=tjM;4l)8>D>&wBUp4T+llp>pamMepx9-uJji@}9(&C1<8dYozZvl(1lrqQ>?E@muRw-8x^t^W9pv&!=A( zdALtl}1)mGR$#kKG>E-&?DHysRe9QQz~=rFNU@0-ptI zAKoZTVNOa2yj&7h$RJ)E;M`Nra@yqFsvv*8GZhLK?JgB56?PsGY*R=xxphnA{~h6e z+j9&m+yXbv<(}V+*nZ;Lu1cfn@#o(>ZSDUW?X|k6Tgb6_#tY??U4c($y;0Lqy^ydW zf#ZhMs+Lf`WKYA)71bJ28E*B5I0I~$J=Z-x8h&uwQAK;P37f+X3VhwpDkA;4YAVG#DdV&CnS z6x9c%k5Ak9-Q6@Hh%ZH%EBN!=xkX8e{s$&>Y~Q!YXw#Y-8r=0EdA}xQ$xA2AtdG8X z+;T(GM_q-TkN+2cD346ofB1_rqx=TVOLG{5Rph?Zovr`z5z zS^Zpf#!T^_$67B;7k1ATowVA#?vvTE)zgjr?AGnyT^}=<hHjVA7(7BJ&{jVR+&u6$=6Xh4W^62@0 zX^RtsJr-{gPgpbW>F2AN%Pa2{or@L9m9oo$vPrvHxB$%0xMbFJ>jYaLzk`fBiA?L~D5=WKMi zy2?kw!_{r+_4tW8+oFFuT~jx&5AL_!yrZmTWpCVjbARpm*SKch`#n{6!qjuxt6BGb zt^W7oSm^EQ{TEF)Pn-VIZEw-kU2&et>U-kWzyEt|t-$MP^}7Ge?`X0+N!mQEYbxkH zw05)N-^TZBQ?9bDsS*CFkonF1;io%m)h~z1>@IG0wPal`F?*Ai`TrlYw`>p9zW#k? zch1Vni=Mp|;d|%&|E>3D|6jeDs@gfxiQ+tJLi^S3{S%lvlXa?Fo4e!_P;h1)@r%1INtEsW+U4>`}du7O*`INI$g76MV7FI zv|{m&la@tOy8^Z{9_(*hDigMqccR&$OA-a!T}o9_)Vf84J63K!+o>vaPvt|5N8ie6 znUZC*Qp0X9SteE_0> z%=pfUqe~XA%G$Q~oQXE`=jo>$nph89Xc3+#`|#%>OOqB8pVks(Hr^v{In$huUp~-}uqtee#}qAYhKrBYKD~dl)>x`B^HsUw)Jd@)8q)P`1PqIPi`V|G>{k48 zXsKZF&5quayS+85)Akk0?*6iW|FIASgIVm;^)(n}S(=|8@thu@!6w(Ld}Gl3C%6cigNjnyB`!z5?yv&M|O6E zrK{Y1qt>9j#+f0uiM0zEzRl~Dy&f+y@06dumYvBfb?sX@a?dWCzW)_ixbO72(#5GZ z{mqB`jn{iG*wOJoD|%Oe_b$G z=X61b%(8{fNs&J!L`xGlp1Y_S`?kn<*Y3q_2UNMI8+PdNwYk=KjT&duPM%UC~SrkIe2|3kjV;yhOp-tJ$k#{5i2qxCdHf>%n#)}|EgIUlmP z^WIlP|4mG})%WX~u~J__)yadEmm98?6_rcr%C2=5Gh{Q;SwE_F`*W z!PTs{Yr5d-t%rX$%r>>$Zusr4#!Q#g`pYl4)P7{_YiTT6HlxLD8K38u_FHVHj!Zq} zR{!nGq65zt+}x9!@U_8^Wuk}A6$Z7|ysF2q)P)~&Pnql&(O4rfTY^EYI(ZUf!_5v; zb!L_oHG1YUp99ms@wVkHwVl%39L^rKG56=(pXCY9w!VyJaoGHN-TRPRlYX_HxWF&4 zf1PK&RkgmOJ;SCyZahYd-n9fxESzlqIWlLt^-Z@)X_YqF4;#*&S-HyP>cM{krn76L z|K9yBseS0n5tok!xk7Y+}jsdFUg;8*|DZ2 zyPdN-;mJ&U-7O^&FQ0dBTWEE>BFbz2yPa`I9;8VsOa4-;xZ3FS>SF2w^NF4Ul0Q;R z*tq7gGbJ%@bPGDbetGJbk}HzxHzPbA7JlYf)3~6zp;%5g#<7@hxo!``l<0*U*{{^C z7CGLokj?2;Bz`8SUO{WWX4FrY8OABM#ZxQiOxh-OXU1YlRrY1NT~*5eB%%+rY3DG` zDYoAr`Fy#<@thOtHTxd_ntf|U#JUMDx^Cu|t7h_Cq zJ!{0)sr>Qw5{CY({Hlv3e=k{Z%F#z*pTQTV>2o>7Ga?V$vp>(ygZR&?qM25AVHPuR`vWX9wBP^UgY{_dQUrgoiYZM(yM>B?iDOXh{L z!jsQjc9&gV@=3C7!d&P3Y)kFk*4lrYoa?ts^0{VA$&AZ9>ha9+W|{A^Rd*WdE?Zds zL4b45$5(%<_&=|oIj5boh(}<~^ZKT#Z%sH%I*3*!|Sz+G|h2=J>rwiqb>07B7={E~>>* zFLXs(`}Ku0BFi4AuDf|4si(cmC9qd~xs^zXe}nR;XR92eGq>ugm-Mgld}5)os8xD{ zuYt@j<-;zj30u}~xppFSpWd@giV{1w)o#D{AbLTv;HQU-3%R0BpX7L+6?Z}Fo>H!M z%h}Xu=F>diIOaVspRzUJ56h-~F#^`_7WA%FSL3dqdip?|>Wc1lm!y*|IjiUMyqYZ$ z9=71zNi%OT#aB07A_TfaLZ+S(x4Qgj(T(Ug&iB8miQM#9@_b|Kf#i$-1@26lmZVZP zVXyNGMS(1#&BZGsKJwlSnNazy(BX+!)clEG8j4h}uV+q@pYU{wwa(YcY>MlHZ^q1% zT(-1lUq;%z>O1uo!QrRgF42}*w4flU`kleil%yapi^7LW;vDa*PPqsgPO{F3EnVO` zm7$D%^4zkXKo{lzq0;r-%`pmYf;Bn^dLA_KoPPOo)r)5{I#j~HFa4B}d8E>)E&ThJ zAm{JBnK6^}15G9#Ty?RS!GT%I@_!w~qx!E^!f8(A>tYnf36t z#)GMROxK0B`mw3~lE_FiJlIe_`F7R@hCrDgVv0eVl{ZK#&(nG05&r0R4yRAyF%hT7 z(_Hn-=VXetl^MObQPe8^YUbB@5?`nM3A6N2-x726%j4zRQW-yRc%>7k8dntmv-z96xZcNzs$Zz=>E-&l z?NnU;p71AGd|%|Fcbk{|7kMu~n`^b;-nR#ZY^KjTzDsac!JGA)!Yt;wFVeof?>ooK zB=3#VeKT9@wij|+Zz@z*n)`U&=fedyMGv@D>i4EsA6TQB{dND>4TU)m7yjKDZ{Nl0 z!u8hamwArl<3)^G`y(8kPj?j^Z0PZB=;FHHIr|g4?+uGdXETH5mdy8j#!zgee6i%r z?ahU?tfJj^hkj1sJT>KC$-7(U1042hegA%Z`|s=g{Qms%_v4=Po#9Ckcs#*U?`pHi zRAo~pcDDQVHdEu+KJ#74@tqqQZ=ztcb^WrXi&zvEa~B=H`OsRI-)2$5qvwGI%EglJ z4)0^X#9bI~44YFtlW*>fjIyrp${qU*`Hb%z_t5qYu~_iq zx!cWyd%i1)CV1-2rsgFQZIktv3Hr=r%sOQ=;neCo&X&?Po|Br^HO2<+E{J=iqbuW+ao%(OiD-ju z0j&<%Z2>)hUM}g-<;qLyxiFjcuEU*OD}p<3FTL$P;YH_FasTyQB0GaL1zD9+%%{Kb zUN|GIbM9hMoqPJT)(2^{)=vzY&3tmnYNKZVHC_>t`Byvk+tvN~tt23?TgrFKO!S2- z*Mf>^YMpiJuAYJ!9@0iXVvFSE-XH@EccJy>z!tckB55Kcd@q$ z&rJ9fvM?#5u~KTv)48*LfB5t_H&f@!e$$H3<`&kC`!6-MCPq76U%Vt^r-stw`HAPt z#4HjIOq4vH@oGm;-mkeH-IpGIc>Z?Z@xZ1jvg+6MW-ptq`ak4(u65?k93Dx>#nGY~ z?^RT|4zzd8Z8_w`zq3_^FZ|97{rt>s@BI4dr}jS<-6nQ%>1OVEvt`mdZPb**>p2{5 zx>a6tdCA1Cm}6w#vp?oS zbqCYlTl`3L+Mdcqkuq_>kj6^kc%u6H)WoxXsxfY&R^zrl)+0!F`H}d z#l><`2M;`cQoPh}nr^az<70u7%s$6v9WlAg(XdiVwP2mt`zb76-|5BGEkZ8B>c`@@CyBIhuKAo5cPe$&L%&m7$+6 zXRseteDNyx%NgGdmlxz;_T&^ zy|UwhM9SCnH^&nkJ(u;CJu*325HsoA8KrvH*6H8OUW#nch%gGyoPR1~%JMmFYKxUV zeLt3XPw;HWyL7RsflfPwZLe(z*!7)TwWj>5?Vfcpb31yJxQvVsem?B;w&bI3FKgAY zg$AL~x=$2;mK|dclob1w_-?a&{nrih@9b;;K7Crr=q#DfoD!s9cjMWE%jFMwi)4Mb zmwj1QUw=5{K}~hyufTh&_r31Dt{Hgoq7~=ii_?1b>(x_;sva+$VBr6=(Rn81C~w{Y%%?>-{hHXyQDz zxoJUU^TQbC@-RmG_gBtrZ#VDR817%lxp$_W$KK6F-vTP?AAZtl|G8P@{wtT$eILau zi~1Hk-_dY%!S~M_cUQZ#8e$bKgpx-LXLbmPWFl{WZ7a zo9cdiF^YFvRC~{{{T}O1TLY>2tbMOFPjKDePGO3~_?mFfzxqtS!S_X_)sdBvPD_7s*DL+r9@lw{ zFX_hRH%dWS;g=%r7OXK!cKT;=|HRa+`n^KFtyCteacaA1I_xlgztU`bk$#+Iv=g=fcI$=WyzFN$LFPU;5@-OuW#XQC+{q1s}*4xz;m#@CMci*4dcN{4VJpMAX){z5zc&`#Ub5)buGgYlZXGE* zVy^1ywu;du`?8-$&6f$5%kMJwRNisC<5gj47{Q{r>RA1|>0Rmz-di~bw$~izv|(lD zbYK3-(Rf8Gl_Bb^Aq9)V~!B(>Kk_-u^vx^1HR)E2jHh*yU;)SiR?O;f=}H z5AWF0<5@k^ru#JWE&qA9e@4d5(>;Gz{%^Jalh@yu=W`dyO6ab+)}1IL{3ot!M)Qtl z=`OQF?zQ54u6)-eFV|1<>NP*Y#=b#yM%_a83_kX?y3X-V7L#VZabdC1>{&lmAYs0T zV8wOOha#762Iv^+p1N^%UZ$6C^VAhKhr;%5xp;n|(azo)k&hyo%G#p;p_Rcypo6V?r&zyA=&2M#{o6uSN zA>E-;Pwm6&J(i8$Q_Mg3o;Z3bc8m6;>%9Nl=f90RCmeG6tdNkVoA^~fx2}qqJo~+$*t`kslb@x=FYj5zd8%dZ zyWU-8r<@G4)~8J8=bOYifBi0HPXmuz&d>F6B$ z;vv@4^|yGx?xt@khAo_b=AV|CbLCUk|M%OBT1{3T`_-QH)F9vSYL&gmajkiR`&FKN zwC=2*F2OVTQ?x5jsTH(&%)O#_<>dL>@7p-Rc+E}wG<;#+^`jFcPZhf~7jt*`2O*k)r(ZT-z?p4>fQhCUxw+e|DV2m z`to59k4#e0=Fq0V<&S^WGha8@k*)ADaDxB(@^gpo|Egb~d#F@Hbk$=M-E{Dk1kN02K-xpVF z>%Q-IzEi(@0#n6d*X7P3p3=`=Z8d(Izgnz*rIOm2kD+&GUga_SP<>%hg;U&tF9*ep z4mpQQMZWnS6tH`e%)Y`my{9UEe);fg&k4J;vF~3^`}wor)aM!LTOHOl??1M~(?ji< z@65@f5AM0N$v!{ZtM_@2{e%?%GxOJe(bBk7e=6a!)!u6p8?;xSR68{F>*|CunN1nL ze)tKOep$E8L8;LxY|^aBN)u1F=foQPTPOBH{`>m=@8|QmrTLf5IUXOq`ZJf(rnd%$ zfsJKP9?iLYV$rv%+Qyx6OyTx52ltkS@6{K)IH$Siy3)&xqCDH}8TCEa6}FoHE1x2C zAg=zyu}RVO@2#GimR)AP>}b1sVN!Gu*Pl%{Kc1`0U;cRh;;#~ovR6{0y;`Iv8?RZm zHq*KCUAFRuHjP`_djd==dHfZUjDnUew%)X?Non0@rP(L1_RaNwusinlg4WFs>Yn%h zt@O8+4>`ZzCjVjdxlE>wrjBLSA%-89-D&zdooCX{C#5|%pWdkd-ZHl+R_*^?e+8Mj z=c@HSrhJy*`SK{y`{-HT#!tJxu8V!rbm~;qs<|FPt_K2_Ub7QUUe)LFWZQDh!%u}K zpMCx9=iAqhZ~wghBMizaL-j-+z9-_y* z&9?teus#?1Ow;<#h6~5vsr1$?eY0u8#S6>!N57Q2|7_pe3pSUl{_6=y+g@Yvn3WP& z&*u<${>_}i9}{P77oK}3QEyXpn%1tupHFWoeEPfpUv^}m;4N;0S;24nqt%ZcXb*mx zryktnlX*&ZzU`)3>yj5TGLK%RPMaxmYnND|z0ooO_M(hKo(XNTYu!3~4`vp>kCo{^ zv#IvPx7mxg1b3fncU<~LWV?L%zru;XSO5O??`d8A&a`Q~oA)14oZ+7Lc=6H6p&m)w zru2VqtuyPqq9e5+Xw8-rdp(xi~g?^kA^<5^V$+I)p7l4#Prq1e zBI~#1i{`E`e|+trOdp@f<>H42YE0r4OQx)3pFUZV^|Jffi`?g9`jw7~)ZCrTC)|A~ z)#z$R{{4Sb#Xihi`Qxl>l-TP22jQobLTw9XlqwvHKXo9-(Q#hYrNyQ3cGK2IuYCHe zdiBh=%iSyQ>dJ7u|8l-kGPA;>y}15CZi2$>(|*0zf0)>9xV+}})A#w}WlNb8D=J=f z@AKYV6qr?hD|da(`~Cv~+jolZ7TvK@`2hFv^Mzp#K9+mk__=gec#Kxv)1_KBt_p5( z2ncs;Oz+9OI>#mZ{mB)|NmXGvsfVWTzBfHIa(eH2=EL1D=HJx0uKo4(>%-5VA7#pw zIavSQ_ptZoi$^ngpGw^2zCCXRgG$}(Gd8@3ibLj4erymYQ0JOote~#B_uZDNTan9R zH@sLNGtYQV)+0|AuAl?&_0FF; znx+x%bmq_0?H72SX`TEfy|k`&N4&?rC6=5*|4g~h{wZ^NVBWZE=?`vI0b!=V^P<~l zoRBv?XI8D(e2{U{JCQYhG6lOUCWGhWVn;;qf zl`LXlPt^Nb6=b@0)z%dguL`o43Ot`&u{G{q+l`BSH|>H~Y+o00YSFp=dZz&A{ozds z58K5UJ@N%M%zk2VteC^0-*&b6x6h9+-){10R5-R{6<j*^zrwn-#E^G z`c?g#)8Rw49>?^$-_L&6$GxXC^ziB2Mg9kkGeSILMC3U(6b4qrN+#HU4qVfzG^u#g zvx7CC-`W59Rq+4&(LLYx7VnQN{;r2A=0PSyklPnA90Ki;J&@Ez6&&^2ee@BB1D z;Oxp$vkPygzgkhLEN}Q{=H%oV-z?Xsvi<5%`PETz`ar#DT>OIhans6I|9QUglz0w* zO1`l(&({o}Bf)8X!W`-WIlMj<8&j|PFoeDMm}m99(e`!Dp(8%;F3l^QWAOB+$g96b z|378QrS(Lw;;1lO)5Njm>Vd2|8rH?nv`h9pw&CFAuHq}4eShzb&!8E8H%U$Mv&M>-B>E2h@xvB5Y?}Jw& zvS0mtdS$lds3A8`E3!mA`laKz z!r91jt=Hrg2~RtxdGy`1XnlBs`M8wbhvQS49!Y-OFh%WnNu2`!gd)FXlU)8g2(j2q zyJdCq;*S27ShG!T-2Mlwbh;)k$P#`U6k#p$Cw;E(jfpn(_BR9jO@h+q`_Fpk)_3F3 zlGIld{Dfvdn%p~0L(6wvc?HvsH0yey!8|MSyGHvN>8$9QV{d)jY(>9czyz(G>>RFxC zc{+zRO7(0S7RWQN+R3jb!dFmSu&Lt1B~Oo1e}AU>p3{6mtSN5KjxoKiK5ELXapLM8 z(OQF(DF)5o&er5J3!fF4tWvea&|ce7>Xn$a>b66EZM`kMh3T){x#mrJqf-^}yr%f` zq!+heUzA$sdhuq`hDf=29-(LNeR`k-f=rOrZ>6m<(#8b^=3)#xe1>vu3D@+FD;PrIOWNz zGx70aE-Oxa=8yiBS1Gx}(bDnS`HJ7$?sB(W5}vW+jI!;CT~C6|3{{>uO*Hw-nEZ0J zRBha{2U62(yQlQeR&P0`e5vHG+1cRj_63~nhiZ4!*Vg|0dN@>1sa{w}+JC9_bj|JG z>)-I6+05zl;f~~TA=URxzf#_RdbgrGHG8%E?#1@s($>9u`uOzo=f}5CSACOx|H-)n zHrgU0`qAw@cha}s(fRg9f40cHJh%8M+G-10Q!+f*?FxY^P!@z_<* zuL2ff`@2s{|Mj*|=bE6%cH!vl`W+FIGC5v_r*{@j-*sev$lI$IKV6!fn{_|tK=T>9 z9&g2jKDr2d&FZ)0%NBBpui-|@VHbYJUHiM?#>_m~m%ChVZf!ex z%ReOf^yb|apKnZUIQ#j${`&ZL_vM~# z{}&^6MBeRMfv}zB3eER-KYM+cdE-I_FOTo_j6j+C$Z6J>*D5Rfoz)0XG~9l%YFSQ> z-o2CCZrqBFQwcVXoM}>{U8#JEKkW7KC0lrkCafsp>03}e^#w=qlB;tV*j^_xAN{b$ zVe%pc7R_&}!MV#!EqauLuJ6lsxnC4(&Bt7wRZ+5a_6g4Xn$6BhVYg;ck^XA0g%s)vVh2x%j9Ne_uu{Q5dxm@zGz3Nf^^%^RSA2*-5zWj~J zf9d_ve@?`iX3X_UQa6s2{n6&ML#wY<`uTw^At94pyAP<;KMM{G+c$CV)35*j-23R6 z(=Vyf^zWqcgd;pAg?~$bGAsRDeg4nuzt>rF1Trsh-xW&B`s!k%)Z(mmzel%Ic>T$F zOVW#!%D6tsU)F!Qf18oc9!KH&cW)0Lw%>2JcaPpFqk9ZVEeBP;FKmh4k#nG;^XY~y zzK*p^e8gK8zi@V+810p7?)3cU-y0=M*0Y@r{<^rm*kZLOqrI2^lqk36o8dX>>vN34 zI<{Xsw?)bFyjqHCsgQq^hk|BH(ARql8EVtB3 z+qiMNOxMlm%dZz}Itgt|t@A1u`M5x9!RCtEC07{g;u^lm3G_&9+Qs+LYITbvQ}zm% zOS`|{l0GZWv!45HZs)``y_3U>nZBB6cW%q9e{R3((t@X2g0H%Mbu4=o<$1Mn*Q>Y; zuW!vwX%78jMT|{Olg-qe{Z8GyuSg(E-^<{P1B_2-3<4Ohb!bj(>()q-rrnKRp z)%n>Lztm>bN2;BdjL?wR)a#U*yqV#?bn^lAMJL-npYzFh zG_s>8+5Tp5#yqFU2_1ok3fKFlD_$0Pv?o)^U}jU>ohggw=GI@UWB41UKl}I3duoq< z9+OED?tB=i7R+|irT)_Ky5fX(%zEFe4i3j$=Jf7eZXoNh#<%`JV07G3zci1Oi_06 z`MXnPk<7#{lll90^#%%0-z~Xk-uo=`ejlf=`uharUi@P3s?q;8_4e^)k8d8_C2ho) z_RPvdd(y6nzHOW?vmU;Fm)6e8C%ICaJo7&--86_1}Vi zR{eKi?U%Mc=(542GCAt9tixu`37!l4${NlWrv)sFkt&?lz%034Az$a*oT;ZyJbX3# z^V2?=OQosBKR4{_VV{ySd(RHD$uaU06Sm)Mh~95^jWKaA!}QZ~se9X61QiZPs2Vn( zyIGbw`K)!BY;~zZ@1y(A=lhxcum83$#k#LvIr>xhCuWB^A8yu0s+;dTap#$wtCLWa z%0ab*QomkXpLtW2;XKF8{c;)3OWd`s*>io}O;_;)A|ZX7OXMpn(v2No)|lvi zWxICPjf>@!ZGwOfPgSVbx%E2F!%tYv-e9bql&_lWbFAU;hNC^XbC>d+b(rXD^XyI| z?@J4BIG>$#P%Kfqen-TT$=#-^;ai^EU2-8# z!SRYOyTy&?s}_V!cB^ta@JGNm;@l+nf9nl)2C7O*6lLs^@nq^h%FTD`afb_=sMzBz zi(TfLxF-HSWs$EH>~8%^GE!atOTrGWNYkl)ci39aT`^p}*n9W&qWw*rnrf=5+d8KT zFrPnd=I@HC}aRW(Lz)_NJ5zYZ871 zDH$(6Xk^q9RHj?FaC+Shk4blYb9AJOC!P4+W!fL~R*>11Q|b4iguZhp>hCR+_^A~b zvg&o{!=+n4eZ2clX17Qlm>(p58TcN_5C1y_*;KkN@^O zWHxJ!>7+pLNHVZ5PhBEy|}rbC;Y4{mQhovYo@W38ybH?MW7aH@PxbkEJ) zM*n1vPoJXP9||{=vvkg$DSRYyYWSPIsYmbawws@G)l4?$boQ%Hf~m!2QFHIg?cUWP z_u%LIEw=lAzOlFex8u(%rS~Zhsy8)6yf|^;n(y-!+i#S*&1Bnb>%DQRmw`um@xfWA zctq-#i?dDh**f><#0`5CE-jw%y#3TQoiCpspFVAs(sm`gwfS?SfY^l-TeX#2+kc-s z!s{8EeCopi{>+v}eb>1Lr>o}m8BLuuiSM@Rq+of?JKXQ8-tFAG@OLIdg2laqPnOMD zks!$u&+7Z=@s%f5&v|k!o@f|)ro34s(*9mR&T;-+ABFmm{Rg^~zdUr%n`2#-W>jZX zCUr{JV8a*Aj#IB9q9(fteb`oZM5%eR)mFZ4i<>icsU4fT*;xJZEaTnWJsNki#F(0e zd}Z8)j@)OJmM~uV;)kN1+Z3l%abCBB9-G=M3T=4K)V|oY>MB!p<_5oOQV;he-ZKbcT!yWU_nHVYVT6V@`q2;=tH_tmAV0X`q zdZCrR;lQkuD=)tZ^OAON6AtdvdjI7@{k}@?Z~tBIbQPX+Y4f?9tDt(Z@r3RXldv+6 zpl?BXqS@YY85e9DUgtc2(HFQzi$gSV_a5iT-)|lNl$zbnX@B&U1ncqo@Z+zvuP^QX zwnnR&`|fwa{G|pDxi5)uUsd$ubNx_*5*cEtXPtdmIjZx>$eF?r30 zn;kQM8EGOq>8&w+SZ;wxod%k3{ zpz)dT8)0eXFShZi?<~j)a`$^)I;Zav)4$Cw4d=zT=a%N>$NhNy`SA1d>}0jl+p8b0 z^x1iLdP5kacD?O39x0V_;maM#Tax-+ecI(}cJM^1L@mq}Y~Trhv)y8q<-@}DSC7u# zZ@1^~&(q7>w@a(oy~q{}bItcnT)gXax|Z(dl`mPg)}P-N`S{A4xZ10?+g0xiK5cf{ zKS9#eTIN0la-)QlCdUId;%Wb(#V z&u?9My0N}@UCx2p-1?C8 ze(&va;bmXAmznRi`BN&&uDg?yO`?;1vi_!yGIq~km!o&P@7S4E%Rf7F>Oyft_xn#j z%igbke{W{^Cf6_A-@AVl9OV>tKNDzD>Qcz0xb!u9&yL;;!Lph*LXynd{8OF_I?Rbx z&p6!vDobF`fz5lbS|=w?Qd+(L14I31b=`vc<;!H*_?K9}JYseEw8B-j9rGQQ&77gv zqqWAT`&(b_ycgy?a%XJnCzYuc_4C_HUDv$rdj9k7^AHTub<$mEC2I;`d_}lOZT>j%4JU%J9+h2xhl z$2z@tmCZ`OybMA&JALOcm|ng`ILSP3)x=FXX`-t&vXq6qRGe2XFTEw)b86P-EoWv` z3N+TUuP)?jO1HFD$#lwR-+Ajn*#gF?O3!-*9CcHzO79-1cMw~}3_o3!3;f zXwTxGA{@!Z<`-;OH*cQ*Wv@cpiRd|B&V(*tVDvkrlc9Aey8D9GsUEGRE9*i+P5nhP zu2wCKv6-b%z>spbb$z{JXy&sC>lr>|FYrz{#n|Ge$LNw%AnP^fb3&!8`|pEZEvMeQ zy;!`t!1ch&%#%spJSB@3=oSgNBsphgW>#Ltj zU$UOQ`|-sJ&G(%a?7!xAJu8YZC}W?+yr66vgW$(6e|Rih_3po^><*FtxkAQARIJy} zAosp#N9?vg3*M@qUdC|h>%0mFzbLW#^-BYszBFenojz~L)viV{rq70wp?Rgd<>ubE z|5JLjE`4E&z@{Y(Q#<~g>~THyX$zNA{Mu)#Iwu0pY!Uw{qQ33yKgAfK+b@28+jV!& zTc-It6Bj00DT|mG{`h3CabN!5uXl+@-K-O4J7z6t^UXc5Z(mUHy*-7O_J)=yC-Xh& zJZ@I6^!+buVYdm3_@d2|k3N`oVdj6u+CsD1R!0Wwq#gd1vrqSDn>|VvJsBXn_QH(m zg^_0#p5~Oiw!}x_#qKbxh?Nm5x&<;lMP^3?&_ z4m(HQ8Qc*%e9ReD2Q}*}_*~9Atq+iHJ1|v;T`tAFTPE+(i{Fd5v<3U0ty4+n(`sjA zkb7rsA)r1rapR=dRjcIU=T7Na*1J$Rc3qA{l>2<10?~2{i-6|$^Y;C54|%kI`>H0( z?#DYsABzb!T-q#_bCj<)SSf^S6;IK}H4~Vx9~YE)rNZ#IbyI?f^^xPD^^;v?;}3mh zi)dK(z3%??UtfL{`nLSe&wQV9;Mup=_y0Z3vFCU0N=*yw-m&1;f}rEvoBm$;CvxWT zESm*;H>nU-RmybTlDCFZ_h--7B1mgcO#W@@ntuKE$Q zWX+LOe_``vzb9!+e(h=U)e4o7Ui!Bn`hpw#$rGmHsd9-0%hpG5?G#k0H`!7{$9ck(7M8YI6T95+*}6Qe@3U3w zKOI=lm{e7hDE515VP&=J&ndb_bKB&HblXW;b@QUEr~K%zlGs&fAEt#{DuA6LJ{){^hfnCutvc z6L{C-)0`Bja&{qu%(vX~mdryeXQztKX4o=$4Qs*Q`lVtHekEHO*kAa(^5ZmR;QB0T z$;+0_w1g#rd&Q%t61N?$l^=h{$!)o( zGhJq3x~w4E=ijv%drZ~xdry8p_GI}nk*hNdJyoV07uqf=g>1RkH)?PfCUCGF?%V9dK;|&y(pZ zpBb8JxVB}eNT&Iox;tyiZc|O&Q`WsIvo6joGd`R6xS`r?9hZsCsZRy_{1$YbN;%IO zZrPyk(0%xEr?GFkh59_sDem4bE+J-y3##8TWlxcmJg9!}Zp3Gi%a8$W&N`gpp2nvDtfgQr_w`53>cIW1omxAFKz4eb+>u9knM zL?2T%Qx5F-o3Z=3)!Gzqv2_Ns1h!6naO;xJGw-5_FYdN(*m8k!W#lOb=8qd<{gA3Pos8+R`Jn!&n5QE zIa5Dt)sIxhDX}kJ7WhjBZgpjBX1^t*z8ob z*crw@U$TYOZ!~dEaI#%LRVCim>f_#@Z6^0?6+ z`8#Wrgj;fZZq5GVzoF!UqI{{~Po|Sn8cT0wW&b{CQor!n5!K5awjL|u6w2F6YaX6( zSYjoQ%Pd`wWu<3*ZARMs{s_eujo&{UFYfYFxtFz-^=|ZoVmTkNk4Fr+9lj_W^j)L= z>f}Y=QjJfN4NrTkU&Za~j!A7bx+wB7P4i;`TRq1gui6yNk7m}FN^6gpiJr(Y3UD{i zIMgwzJ8f^;q9@FfGXieK%@pxn_I~DTzFr5nVDIw4qj_sNPR?IxSpVik%5@*UJu@bs zoW1*{i#YGjieo~7-xTAg_=;DZPxn^d-)L%Tkye#lyl8!5c5%wl!k$fmGc=oeW+@5( zXi3oRTXp5ylMNMTu05Nx)i3Yc)pIvrZE4WB_Uyo$m8twuGF28QdGq5JXWW=%62jfZ zxv4Q|ZRc6On_H$m*NM^Z;yWHyKaVw}irezz-nSQLCiL>JRw=HFG}$z3{sE?(`i@Dy z*BJH+OwVa7+P0DNmm}{4#)w~TqG@t<%5R*{Z5P^a=l1vW)8(R5x#sFArL5dC^O{j`XPG~@>`uQCvVpPw zLDS5+0r5o#K1DDe7vR(@_#$p%eR6ua)c&Nu33ueDREXgU4gOdbKv@?$he^GFP|Fo_OY0Np<}B{k-AUcZF?tEl+yz-?6X%eM}|EQ$RYTYR&rfDvvT(RVB#3 zOAU9=uvskHTR*{W4o?eDip`Cskz9dmx7^9*eHr|eJ-Gb1WmLhASzA;-7`jZJKj9kkry{b`sR@o-jud^iXdOZrVYd&;qs?&z!(UV$Q(+nmX9-hd3 z<%`$T59gKsbbbCJ8fhoY%8{(&R({iWXVj`CD>*hlxhZ$Pa8kE^{ims6g{RJ6p7CVQ z3(<~w8c`j)Dra3S-Y1&;`=H%koBF6(D~)@Veu}gPL~WL83cJu9HbKHX$lz$7C-eWF zbB;%IPMW@WmAN2EQ1tb-9R5>hW^cEzt^4=k$MxsW=U>mzED#QQckpB4vS)(4iqa3x zNAEkd|5Fz~f4+H+&}xAdzt#%WuiRkEFS_dsx9Rq7zB}yFdD(df&3*4K|2eVZ`&zBP zzb_vzKVScU(;cm2y}#t{TU$FV(~i(Gs7Vg*+~s;+d%3~>zSL-sKL>>;p5145?YLQV zd|cg+4cClRrnk9X7hm^o@kHN(4by*CEV$%wb%EdO*=w)%-dxA!6S&7pJKf;eLAB)i zoX!m^1FtUBWPR)RuU+Da<7D4s(;PR)Z(9(M@17c}y5+XhfyJ5G+%-zoLN|RmI%TXk z$hj<1%gN@u^y<->Colgy&JgdsQmUDHYrzkfuh}=wdu(KX;IUiZE$V6xpYO)x>`ARh zs?NFi?$a(Z)O`PL+jH)i<*ivcnQ@Fh$L2{bDXl-F8kW(fP`s+?!pZepPhIg^D5>7d zvXQH4YmCw9TEUiweNR+bmRW6z37qL&qc-o$F82I&ZC=q4ZhHeh&&Xc8>gn2#uP+E4 zRZ$C-P09&>>NV?R+435 z-TpY`@8`nPOAl*>8yE_lcx=}8O=HFUIZs8TJLI3OnXS~fan&ko_M?AK*0r{L@n?&& zW_qq@xa!fdzjxL&UYK?LoYHN}WI^^bkF|``PnU}b)-CAP=kzVCpOuB9rQMGgN1$ec6!vuo~yYv23% z-#_rE`@Mz5yt6~@33JXYAGwrUUqY%qy3$#)BJ!M1Z4L?cUBFqY@g~;5QGDYY4bN3- zbI%`ncz{7DqgP2-W`6vMZ3*@HTld6l(LVn?BU_*Scifa(Ubib+!IvXv^Uv&J-}QOd zop}#>;JD(-nSieA06I(0bR+ z5;vFMP;;_TfB5*^%^TAbZe3jGc1-k4i-S0?K>61>H%{g@7rNZ4?5sMfaLnV$+AsBY zIxTWNnp{8L4LD{Mwh(vSzm7 zn#*rBV|S+{Ciw;??Vq{0{_vOeydSn_{ER>SyM2B9ynA`uF0Hq>=WO;5WH~+U_Raln z9)E9bJo;*+-eo!?iHH7Nj z|94H_pT#(bv2uG%Hlqq-y?uJ+3Y7zb8{H3y&3){)A!W0GfRUqfzpS;6s`Oifvm7~F zHNSE-t^N{GHs8Z^maO~c-Wk_6O0SLbXlUx4$MZ&v&nxX)VcY~ODdy-e9@e|xpR9P_ z(r!GDP2~NGh`6ZESt~1ltb7-+QC!gRLsE!A+?i6|#I0VFeu_QcJoWrUCExmMRmI_% zjWX-geoYi{7w*sLxb-S&lIFCYwmM1u4{7zQ7-m$}ZJNU`D;6~8n|FoEm&IL%$CsXa z#FjoO%AIYJLUuo2(d!k{9Jo%cSyq36b;X&*3PQdT_b*LunfIyb+{A@yVrx$o?K>JN z_VdA958nQyKMTH?&wBVUZ0r53kNc}69@R?(>6HAccQ&nVo)XLw)VRXWrn2ax*DDvx ze^X`mv)fEb3T(U3U?_1Wm*MaIE1$V#Sb2+s6#`7pvTcjMd2?@LsO(X{Ogptw)!nrU zF##*s6mLfa37VPBnk)L^tMu;Uk9RNc*WM(c%oQTAYKr-b!gXh2CUn|qp54)Ot-rl) zOx5c+ zHSJ1gs^g6vi$ZJG3f+6NqJLr@cVxusr7n%1|G2rfN{X3Z5B(#iaVjt*zxn00!fOj= zPE|b2EvtM{zpXk@Bv8a8@{z#Ogqc$W)<-NAS~&Y-!sB`sjhvYQDf>=Le`#=YfBT`O zp>@ngw+j4I>s*66POg{O@4qxm?$t@(m+?10*8cg`KXqO2;}tH`5+xtizWaFYWRla< z9o`#wv(vRshHagZRI@Q-E7Q6sN=sRF&Nl3xFtg-M`I0Pg`OOMUlQtjvap`fm%;LpS z8&1fsKOw7_bLIb!EgJRbC67N5@Cok_{^H1-^6-B_iETC8;<96tXJvfye;&;mlVhjE zbaJxU!h?S_4OTT-GXH))Lt5@z+05;~mocAvC;euh%jQk*x^}7EvfUD-9TB^ki&Y_0 z-v7~@b5D9jiVd3|6!LQ<|7cWTSA6sB;)~mXrf$=tPX^{};pDo**1~A3P|v(M-q0;D z`EVg)U#Eem+{1>i$t$jJ3W@sYJ$G8sQCD|Gzo%*1Gj9FRImxPVV9(2`Z2azO3U*1B zpXc33e0Kf!N|886sgjD8xN8g9PqrCVMBm8Tx7E@3Sb*&5{M z*1}*|D(@m?uJm|9u}WZLz?`W|Wq!=(QT;pNvFT%bHiO50bA1;TKK|dm)0|`do8?V< z%X&O7I3IfJd-0w~e!kZ(jfZVZWRtPOnZ)s* zsr85NPC6^zzfk1IoV6TX@z+@!Co(f0^0B`+52C{%qaP@3jtWEZ*0}ylr|?nc~HQ+c`R$tF-P% z9(ijX75Y!VZcg~={n@uyX`R=+yf5Uxdq_{T=$*A%$EJTTV3e(|`u;xt;`X|b|7ZHP z7>0*GUKo9g{qCVZ9pY;qL>?|mRCRkgHRatVM@NsR>*5qNm~XN*af(b}K3c$*+W)`L zY5He}MTr-qxn@e_@9vtfTkaJp@z+mj)4RYY9?V_a*EYz{zxGG+i{oRyiP^l@&&>2* z5Us`gxr_Vht5cIoY}V~FpH{E2eAf#{r{kJ^yJHrXv%T7AdARUyWQNlG-EHf8-PS%# z=CNb`(%m|{etF*8iA;*e7BVVbW^=!rP_aJbeA`>A?wiM6n;-6M&zjOXZ#7#^nas@6 zBKx!IZ$$FmY}T$h^hGpBJm`z$p7-+)>NS?#X!==u$0R1RqE&3d^?$0D&+YqRR38yI zPfX-f%vb&N?U(y3XUx3&S7hV#4PPsiKfJ%(cT%cjJD1lQqc%sY_4C)oA5?#1{QR?_ z%LA$P`)7P${9x4K%Tc}L=QW2t(FMQy-Pi72@l}QGNiO%EZ*GS^oJez~to-*?=8t^qvb(ri}|0bl5`|GBe0b#4tjMmF+eO_|s1Ve0c zk<0BzHGj8!Wc@o^H2nLw`MX!Gez=bN+BCUau~jq5H!jSx)~x&cpv3^jVZB&!UFxj&JTANEE|>Y64mm0WwFGbd z+}JYxvanvg)v5=HZ4*E5>|qN@YvSB;HAB3>W&``{NiPM(C;tAJVeDqlee&^*gF7xO z9i1E}YLhwr!-=2YCY0{2tN8Kp@nfw|BJ-c>FEE(-`sKa4%Tg|~Ix*XGu9Rw?w2W&@ zG%%b}x+k%wqUqrak+RJjo7(?aS}trca;oq3(J~VI?dMyh{i(inj@{o42XX=|^VV`D zJWSmw%{Fd*!gw;@L{#{YxeWosnU(wUN}hbT`{{i|WjL z@A}fV{ZV4mm89pW)aq`i4@^;CHM{0nh12_n^tBADlK0%Z^(no4i$Y#rIrnSkt%cQ# z<102CzY`Owh(cQQDk>MeiBeiO0E>8>#I?{V*w`blomSsE)YPFhoBVFu{ zoSU!I@8ADra*O~pFs|G!&3#w(d(+eK)(@&n`@4QUd#JZjbxWB7`{W}P z&0Fgyth}2O{m;m6?qS`Fhf8C;iyrJ(FSke)uxU1LY7Jr$_H|AXe-V1@H-jF($~Rf@ z!!tsZnnQ9&JGr{-;WP^0Y-RloSvA*m&9?~lGpxU*mAd<|<` zYRrPW8RvHRE>T}~Rd>#-uZ#9n{{Hgw?eDjfe&}=XzO`OhXj=8#Q|HoK_2~yrU%tQp zOKjYx>a$0mJipepWX^}Xzg9e-v)4)@Zl_59(ip4MYE3B)3(-4^{+vG$aQ2as-pl{} zm){?Gp#J;($Nitm+EVH_1b_N?f5rc~C+jZHV>A4+xE%w~HTh7$y&A+O9A`h4H$M!6)S=|tSf4@y_lyI*80 z&kk8OyKss2A8V6pvr?X|$ERH0A{C&JU2h?rc(lwSIdyS&QqkJDJ#h`YBW-&3%t(nl z^<+O|E`RvPQ!mZ4s&}XToqtJM^`5(0%w5YE2k}OlTloD z=s5F{dUHLM+6lFHiHtp%1x~=E4H)lBRV(%V)#7IT z__9bXXwk*YEz{Kc9C$-><*W z|AzSWU>k9vKRipmF8Eum@YUTyn8);=dfCEDX77CCJ3ekw*k)d~SI5TPD0kAX>5W%| zW}IMr=e6SMLyO`J=ZuHP8w6(0;0-*~=@`-L%OfJVY?0x&w+_3xrCh@1kxkqv~`@{bNtn;rN<4cNWeb2E?IdI};_EmAt zQ9m8Nd3~GKaL_4j*~Zijb8b|6%(xyA+tD>4b-(JzkauDCW^cE*T{q{Kf$Dt2mGd_{ zBS6lFbZI|8_nATNPRQ~z%<-@)1~6*a(}US_p6nidm^5E~A|kUREUiFh_xYZQ9$&i-TVMTndG_}6@^-d0k$w+U zHZca8U04~kWrOAqshv+BF7cb-V>sbVM2Uf@Q60nc+x0V*EkhavTl`pAxc*L<8oe;= zjjCDx<>=G#ExXPr=sCUp(0WSZ@Y45NX75U8F;rinaX74iBHZYAvx z^kH41-D&<_NW6h7X=SY9>?isWUtGVnRGd%qw(jK?SKPARWM)84xZs_#rnx<6Op$jr41lP08iKh`wOFnO=?%xb4*#*wz!!P`H|ob9N*E%xu@x4T8_$;4g!fYXhgZq;`YoQ@@mu+J;I_?@ z5?zbzVttreV<$6OOl|UbqNdV*SD`jjZlQAZf_2I_=bXEg#}sMt@a+yavzSMs+=(4p zSC;+hfBfyyVWDNcj-tUn>L1Q->-Rn3v}ElBr^HK5+*>r%nR=5ArqYL~6Ef8x_KFWI_H_Iy#=U^m?-y|nq&vB(9N zp4~p5^ZMK2&st)$;yyaD&p%=;nO@~8GJT0f{Z7>c|0I#D4HY38N0cw^kePhMZnB=d z`^S%*=CzKe?k`>XiEs9O5$1boh7aCuVL7e=m=!-*`@^2x z`4?65@%w`ZZ*BAC?%CJXMXq%)DNU`rT#&v%M!8G}}%I~-8+GkHUTGM@^ zYG%YM&P~f6zv5Qj=EXVDJn6s+?<)3HQ?%CJSts_+$71rswePm>`tjxG&$lyTI3Lc~ zrg`{3w>8`Rp5+%Gd3-$g?Rb6N()0cE@BJ@U-L&_2gD>B6uTiUcO~Lp>yY~^8rkJtv*ZF7JuDV`OC)k_aTPqUe`Iq7cqCf zuAWu$v&6ph$h-~b+}7E9)LFW{Og;M3kF(G>RI9$k=vj+S#=g%oexB=|AJvVFeBT)8 z{AvF3>R+Ek&zb35dVafE-`s=8_jF9RvB|AT>?dQYH&#zRAgJom_QxSj;#*{@@3td9 zzeVgi_@Y}Oe{Km2*M4XJVq>MmzAA$?x+nRpk8cyMWlS`8p0)h^_T}+iH#wf>O*U=e znQmJfutL_ZzUR^V9Y+&tF1v6&NhtfiC}aQ9^OrZ9=l**6_W5&vd)xOPrj>Zum+unz zJ5&B(`s}~QLW+D(bMN8EJmWOaMf7HsNP@uH&@+wGIj|)>k;hP0%_Nb3i=l9gyVrw7A2RD-nr2vuMhf-3+Ay(U ze|4YkDq>CjC2XrB z?*G!VerUYv;^Lo~nM|io=hWXb%2S=#a$HlkIxv0d^v07}>Je`x&hFF8C=S%f-hXJNl^2k;_ov`@wyVFYYVcH21h%Z|?C| zn&q$b7v4i}rJwxcHQL|U>TzbDzdk!V@X#qC*{>i-s+7wBipKQ@j{-AQ@>JR+woILKe@SfW?ECdB;iun}KTUqkd1Rf5N|-@r%8k8DN}bGi zw>tE(?E1i=y~M_Zw><97zQ)O&Q#)?ANm_@gPRlxXN_1LD)a%Rdrmy}TE*1va|XDfwvT z-19lR+GtnfIiAelDU}whK1M#y+@1UA^zG-VJiN_&ji0A`TFI@h*k$YdKy>=LD|3$e zOiW?XP!AN{@HCjK>yKh+U~S9C%f`Op+ngR~KYp*S_9kgneWS~ZpxYHXYHUJxc+)2wvcu;9d@hCS_5%?r9YkLA2S(R3)@ zuPDQM{-?)}Z=dJ4U$bROz4%3sZKq@8B=@P8z*%T?8+D|cw|=cscnb%EXkUl zadBF7?`K}8NyV2vo2KWsZ|*hExe<`YSo!qpfs^;;RCmtrmaTYeq`Y4`;9Kv?)Vo4;H8nqfe|~NnuDCXH(~Z=S$_O`CCABiimDvkRa{cO!PS!G( zs%?1}X=vKU8>}q5>u{5_5Nnp$>hwHO_dJg^(>5;Nw~SR#fNS^PDgP^e|NHrR_tgJq zJP*t~#?IGp=SWlv^Y{HvDjBzneOtJvrRvJIE9YwCc?wyxqQaFuJ}N!;cp@AkRTb`T zKe0@sq`BCY>)Q;+%85O_Cj+K-N^Rmuu2)^#s8*&jYej0228*MDol}ZYu8xm^#zOwT ze}ld&i+DsofA%Kr(f%2Z7h69rRE*r}GqqH3`$F{!p9qQbchfqLx#;z>MxC@$m^$Ty zQi5U>$Jf`@3~r{O{-^F+Bu@*RRQb;HxcilyD@osY++PQ8jqU7P%{2Rcq~r_LcTc{i z_)V?f5azHlf> zUwM68aj+5lZiVt)7H?#(lxL|)cVF3e=D!iVfr z{MR42Y&2fhByh^1WtyFX(4-ZwCS04;`r^Ij``LwGe?Go^`czp@??=urjN3Y_dUp!8 z&zP)vYwcW~gJw)}jxF;NJarsY_nX}3Ss;3Oh3uIXZ&R<7Sx??xv`xC+rZJD@ex2H- z*$di#iahdM9H;TS^Fu0wM(1Nii>95*cls`iU!JF7b8%A7^{>C59E#fzuClM6;qc{x zSObwef$=plIeFcmeim-7y3O{IgMYW(DYrfQuJ!D+zRuQK|Hk(I`+LIQ=jA6~I=8j) zz~8yY-#@D}|D0FxG{{C;OGl|N2TW>LtpLcxP_v_2&%U@4a7rCI#QrI_Jiz_Wn%eK#%v9Bus zVR!S*l;dYD7FQj!=A0|V?hwS^_quH%_kTr=V;9XIG(6{AQ@1=^HZOm#N7P$mMHM;S`@%8c}eSAM(d=CPjP9tBoqs( z)T3uGRxT;_|1)vX3FdDtGt*3c)YCan$!MMnYMgi~>D-g>E|+Pd36^&`&E_SCT;x)c z?7g@)V$!e585v#MR>*m8N=RDPw`EOP$sA3S%CGem-zxGqzIeRHcg@@aFCT~P*Hu<( zvqmjG!*$V5Gm@pE=NpHr>w(F=CdChgmW2OywaDtZkr3D8B{%2j#-?NE6pjh-Z81o2 z*z9AdE+tUyb2CWtc-P65%ac6sty7WDV)|g_AHk-hFZaRsvihPaMJ*RzCGZPQoNN7o zOGn}@r;nUw{r5GCw`9JIQmw2ujcaU@Sd#R9#=Yu|9_eB2!c$!~Yi`^br+D)Z8}rJL z*_$Wr>a2Q{(C@f3L2>o3gKq?j*4yX*_}ZxbV#3>pWtE#%Gtc{+mw3Hw#vh%FrHg*+ z?pxliY2&4ATQuj}#aAx=fuWTjcHbzJf17mQerx}?h}dP@eJgKFzt_pgRy${LB^A+9yv9wlWVe?k^1r5>;*YFtcx|Y*%oLY+pFKOeOm%+?2;8}m38Ls`)~b; zWUdU`u2SSdrC*lptJ}Vv75s(0#*uSOGN zM7BExuSmT*efbk!C*`I${~m8`xy+zhUoVod*K@7~$L<@|C5am zXNPO9e?CUNeOsi)SZ0u*ckq&L*QS<-Zo4iXyZm^&uKVx1OH+-NHSg|V>6-Ia^04Q| zUCr~DvRzE(nctZ5ypPS|kx<{TZFX!N2?Xm*q3p zyp>G+bL55GZWHMl0VlVdS^eefx-UoPAMMF5Evo$cSk_hj?OfKSRY9)C47+E>PQC1< zch`IV$)N0qQYvS!9nMt$^)-IpA|W2uhl^6rGyMExt}w5DpUvO>$3t~qUhR%pa`4$p z)}2#lersajSvT+0!7ne4@jlsMXD`Ml6LCFJn(2FMyYKfCi!B`5xYmAIsNM8HQ+Uf` z(G4vM_n!F)#<4y6$`Up4SIVDL;uC%x@O$I;HtAFJA%>@VFHK^6gBF(rOc<`<=aWB}Eu2;Kb z-I=YdVlE;%Wiw1)^xTpDcRD5K)5ME5k5;aqDxjn+>^_w}ZwH5ne{S@g<)(t_ztxqD z7_=L9i~N5W&veRs-YTUprzF*VD$x`4I?%Y!-m-u|<=`AuHvF)p7cH}SU zh!CjgHQti`vxfKnxgUHpf3^v{k6*Iu@sUiHtdKRmz{wzPC)^_6GJpZHulgGuq_4tx&pDzxmy( z6&5?o^;Ls113cFCEI)MrL|A)L>gQ=XK63Y8Yeqi$cX;*D+g}6z>^!<>+xxs!?y7&T zhOzlEEFy-ll-?SoY`kH;Z{fxxC%B)x6sGuF&fS#H)}p%lfZxUTyHQd;w;OIe-t+Cs zj$Y~dW4SS=?>1DQtdq32+n@7=dFTAI%Y=CMmFjsfpQIRaM){fC!pl9+j)^^6pjp4c zqxk6D*|%qeC%WZ!r2KUAyZ7ho-|NSxKYu=be%MEGTmRfsLS@^NZhx<^pYHrI;o+M= z7xsG}x%{sx>i^`(bdRXx`edB2wO6trX8QcrJ1G)6womGXICAG+Ho3RXFwWY|t@v8# zi$DVb#?(^R+2@*Fd?WLB8Woo>4KRV*t_;+9Y#rc}8AGQ5!{eANq zYF7AiR2AmPnExyd6OP)xNQQ&+Xu!+O4~@2Vws&j@Tk!7dDYl!oKgEx{beZMgFFzwg z^uet|aVC@2ED>ybSwBU7#q0u|wwkj$)1TKr6|ZucbJ2hQuFoeAv!^$ooX0Kd#`Ta( zfi;HDXnR8P%twpjFU@vf>!?n@Uhv#sx|09JuX*!+T|WF<{-5w?zr2lS?!)UNy zR-o)3v0?V9&&BIjin?znZJNYIEVk)V*u()K|^^W_VvB zdvED>i`RLD*Y4h0yZfN1ZRz$ayJv5Icg^@q@29`_*YnShH{;1(_&U9)`Cxz1ocg6N zPe)Gsy?k$Nj%mxP6Gx++6O><`eYP#=#p#xNr}lK%uX`wM`Tx_G{^`e$_y3=1%lANP zozA}Xpa1?{{`~5plvCOB(nT%LexCDeUU2=UCu=@io>$wuO7&ckX5$5o{GH;G2iDH| zx8>Zoj}M=|K9ziw^RA%6>I`bmf&YrcZ2g&)%G3alFe^j=Gyq@h`EQd)cwr5hBvYgl~^C&ezN%O9!JL`#dlAA z+HqocWz3v=D;G<;hM7)m-R@MDFU{^1ZXvt<$MZXmPj8<-ReeXHNp6qkx`p04TvvsUb}_!_yO$Gk zZ(dN#(z`$AF@BR&G4!4nb;->1^H29yg$m_w`9jlDwNFivd0n}n%f|4?Q48B8^>!~3 z?j)HcE!DMoQ2XU5S4H&nt13tSY}9(}mQeIQO=x0z<@^ulluxQpnVNF*@w^(v&vWXm zd4vl4Z#Mm&RQN5&{^I@XWr`NbeTR0rI+drgEVKNmk;n6#hv&KP#MDbClHZju=5+tO z@m{?{QqKHMq{ZYzWeSaa{&{Pewy{0ha+$M!zsW4a5Y@RHyNoNgwx8X3cedCri%c(} zb(M3t-bjRO-fim3P;ik;c}mES{Gyw4IMSb7Vk_(~(|P#!t;(_4OXDmy`=$J-VY@iF zJnQ@E*pFi1;vnYJ@&zvTG? zj;7z8|JC)k(yINYzZDo5@J$JY~ zQ<=3`=&p##8q-5E5$?Nq81ObjdGlfBEw4}&!kLY^Qm|HuYcyj44vZ@`FB1} znbC0gcLGOuvicjh3l1ll3NN&FUzzxR)wZ6Gsf#*AjSP*hul*9C<$76*FHJySt6~RN zvhU}_xU0dRoP=#Sq;76a44kjxRy=LnsX#7mr*~QkKBt5H8XHdsc?-3i+QP6*#LXl z_8nil-mcmryrOiTonGJazEH&`rE{-TBloiGj$GIm{K>-p)b?kyZ)j~3QjywQfB9bW zssHbEnl#}<&zqG_JyJKp2px^f^D~q&jX5|TQIP^MPQ2TJ)+c!I9R|f5$@T7Rk zE`@)Y2E9oN-R=8UL|&Q5T48kVO6gyIz1DiQIZpk#=l^i0Pjz2H&|DS%A^UaOI6&Y`D>&VdtaWZqKnsAO7iasw7J}JAfevXDRkHOT7|PB zYz`}**9VpDl)7|=`TaE2pj$eeE>}e#3LIB6i2I;4ZM6`?^+gwwrxq=7VeJp+dAjFX z(8Q*%y)7S(K04RMD|}CT8}F`|^ovI?=J=MxPLs*)P+NIx^1j$W{^Kk5p1Hxd=w(52 zStpB{k&$44oRx$DFY9JCp6x1%?c4tQEDFvE`sv}+ml|CEb;Fa8?^X#;>(4H`uVE3t zyk7K>gMiw;sUKC@Q`5Yfi=CDgA9`u@qEveMq#mtn$4^Fhi{ENn(fDX{$F&WI+Kzq* zP~TP=e98?n|N3hZkzVZBhLMoCBx}enQJR%na)+U3OLGlsb*RC!aeKS zFR;GzRhLNJcuhkrM7X|tN3F>Lu6Lr&fme2v)^A&DBIn)3BzSaVKF5qBa*O>+1kWn0 z?&qHSMulOeO68^ABQe)boH|=IX9b(crU|-9dks0ft-_toX~lZXp7G@K>R375B6m^O zJ$wiLS@{2|o6$0FlAYM$Jz_@Ze7G999d!$~#BAOkCX^G%sJg7KOhL-9e#6wSCaLAE zpH+TtI(cMC^h@ohelan@ApMETPFH7N@XOu4Wu2tM z4xPfBB~43aZJB-b{hI7eGmJcb&MaPEF2ua(J`4Aw4ZGZasjTc!I_5D?=UeJg&UusN z4ulGR4mr^s`$pBr_~i10t-+mPJUNE-$)9ib-O!hw+giBAJ$zYual^Ym`Mp(3o-60f zz4^)e&5rlVncTCU?ARgy__u#i($@NuZwx=L*M4QXchbh*eJ|x_tu9MfSm`1&+o{a) zrk0*6!~U3B)A_r%&Ja=7dlz;(-=$8oYwIa}&5z4<_a+s;-}y}G$NdfePrd&!;iKcp zDNG*qr_8S5-fn#Azk^l5{o*W#L-}i`8HB&z*0x;U zYS)Xm)i;vm@9mGj_)Jpv>5nZAIRe^DM?}~RquUqM{n^Dex#N)ee3k{$>=XBEB-C`p z9z3$gs%;_LF6PGv4wmxT757YH@ivp!;&b_>e9y(;z|W|n=hm8857HJ`-fb#8F|T=U z*v{@nuKln7yh-(7dG+qdC7la1ZiLTE*>>{NZG(lcH{F=gad=IS$(2REi@bXmcEtGQ zBqe27%TM1j+c<~$$B$jMUv#w=PmwyxJ7w#1)ftST_0KBQzMb3F{_*)#t4iZPVFh=~ z56o*g7NekhyL4qn-i+Np6(dESyDur}YCpNeO*rv)TII5Uow4t1_Iy3H;&)PG?PuOK z>gjcnVFxXArn&z7(BitnEF(>^-P0k3*`;J-J*$|xrH?iHPQrN~Szv0xPV*)&0 zoT+JrH}6bqc2#pJ&6xPFKHr z9KYpbe$qs-R|^ZCmgbmkF_VtEJNL+>M&Fna+!olGzFoX- zst|kj>uU%4wQ|M+G1L8DVb=}zLTpXJXTmR&Y$=JEUMQ;go4 zG@I4_zIw_s$L;vtgB$-w`l{7_pP>G8mR(zB$+m5=Y4X48FG)$Zy zmLD&#nfz;ZTl%Nk^!VJl{VChGSn0CoF1qyo*8e+qllU4Z?29~=zx{T><2G~8{^`uK z8O`eF-xWP2pKTkoC1>}yRIUb=r_yWT9kel9w5Zzf$tU{_sZ;Z}uGu^5=jQ!& ze;4onS6BWs_S)Xta;7=+t>4&g_pRRWS8m6PZ{gy3)4ad?o=*MC%lvN3-k;ZA{NA0j z)Xcf$uHCiwcGDhg`C^~xvHrgOlKXaV{yz}={k%`=ZNE&t>9bd!YO34Ai{ITi6Ln)r zxaI#%>vfF3+n+Y~{`vM^O*BhjRnhv%TNhghEweM$<=wZF_s07p|0`wJ?!9$UOe>=P zhx?z;yBTc%WFPsLpZ{a^J7vbH!m)E6P29w~|G>9YwXGHnO7+v;u9ucCXKT+%Y2@ES{{@%UM?(^MMkEi=+pH&i1XWcFOY{`Mw_6NQ(eHVUu zdG?WTt##|nd!%o1x7NR2sk@&)&q6G_+c-1PPU}$X?CrUQ$FKkW^fR+w_N4o@ zIZJ1-A7T^#CD*L6@xafws~XI>Jxo{+Jnk%dsvS`r`6cLJ_NUOI{1h$c0<(*IKPq*p zPB7@5>T>36!Qvywt6P&!R$O0JaGrnlhAGv8$<<6RyanH_XV2v4TBe)Axr{9!=|Q5% zp)10k;T@(tQ41&Xt`su$()7-Vo~SvYuAYIxP^MFQPsA$ez+B!7_Kq4_OV7*j2g?*s zJM0^IZ=cPd9b7w9KAF$ant86_gf7dh2IJ%6+Z-lNvJB*jFRb{#v3l90yn%N_+ZyhbB&rzH3qNus;_>b4COgj4nUp+a;qat0N^F43w(Q^6u^>zP0JUxAU z`TY6yVNKpsFRH7S{a9em^>&d3dseE5`O3y0w|1`ot5rCs&*Tx;%r#epj_o}varn4; zT9et&MR%H07pG)im?Pn&&(y21>vqe67B7JkrM}_`DaUy)y!5a<@WetV>hyy%myXgVQGNvyvl{pG*XC+44Ou5K<9UO8Az&hgwk-&64Wqo~6x8)K$V zVGMje;}P%83V#Q$*S{C*Zj@B7`|a%CN1(0qO3rfyCI9;v#H~+Pt)+d<(O<|zc>E8-PV1R!G&9 zcYJci$$U}LUWUI<{8CQ*-Nv*@GJ)O3Y~ue1f8_qpQS3etVH&_-HsJ_co3kR*gdc@o zCKcZzk1RDb=exubdu#7AcCViTfbGlFD)Vk#& z0*+@gW?oo4HL=d~j`caGNrFo`_H`P1&(h?d)cIs)Bqy% zkDu$dvaBxOT+FU5{_<>J?=P7d8~D#!aL)=1(>b|YW!4tEtPszxliEVuJa_LnJ;)Ug zR2H1K>V)|8o*9}kf3K}OFkigz`LxFeIu|UcQekDhl;U~G`C!xZ;028L>tES2+h6Rr zz3P~w)n=x5|IKo?V^zV-pF2Fh2lAeAH#L}>&U`tx)%~NWidf?Xy(inFp1IyT`1$QO zJ^% zYYtZ4S3UD*?ZKOSpN6q!70fI0v5RW1|9nwuPUz(Qd#_JE5;^sip!SkgVuf#RT>qik zS7yGS@0$JJ#Vg<5+%A*n>yUe1yW&Fh?a%ja&080E`|{qb>a38g>Uk_@k~bG$yft@P zK$-83z0;$o{PVfL`qbyWOCC+%lJ`uASLpPgD2}~Weg~7LPUneY2zvN=+SZ5Dwx(IG zwoY7pzFuCgz9u4XmoMEOSHORg}ZFOEBH*tYXM;+S(}YM1NUu#S@+eC|ua z&m_J3n0CU_eCv19l`@anbdn~>S*&KsZ~V#_yl@hS?X0D5iW^sIkFX zlgA+9z>19c9mS3w6ItYl5>%t~4-rGX*Sb2Llsf!$@}eg_Q|0b9SWkMhdznbP@3P~iY>TV~Z`rY$@|+b* z*?enPh~Lv?&W0NW1H1)eZw2Wro|F-`?c$k^($leJTs%q-^<(ZlI)8RgebceRBVuCS zHtV9bZzWFpWW1tdX`aafU$-28rlpDpzBXmt*sXO#>M-T3#N9;@kr- z&N@#&ClqP5s86)gc3aU=v%atGl2aBJww?;zymoVl-_G{FT8p!vtX>2ucRgS>kgTX) zcZAJox$f(f=BIAc4V%N7xF0$9yO}TF7MW0~@nh4S=aV_-GcLNbE{^yPm9aklo57`$j;tvM|J-0sNG>$F6%zZXr)=4&&(0^4&qQhK zxJ1Y$vi^MP#d3W@NubZssSiRb1il_P{cPv#<9YM4_}`wNBbVu~!m;*DYQ>J)8S)n& zr4_2Yi7~c&wyAE$ZJV6WYc}j<^8Zv48(71|RmytCRgkOf(dUMPH%=bTuNJJnT;Ka~ za@XmjW-g+>J~G)U?7DCKr z*(uYjpnrkcVZp}btF*iuBKNI`5cxDo=<^MZotuw^Sf9{f-0qk6i8C?iTp+trmDu{A z+_lobcG&;?`SAErx!KYRlgyibh-$N~S-bFg{R-nJRV>Lnmq%^<661N)dDHHi|FsP> zeQq&is0xWqP2lXC*)Ln(W#XnHJbCF)g~Tm9$@#8Z?2r8}e6iTQkM+yBH+(x@*PK>l zn~-%zqVo96l&AHd-~D_qzkO#6AQ@2`J1`{d@=EWT+zyXZ&M-kQH#jQ0OI z|MS!S8`A|>GG4Er&Z~0&X8Cbe@t>RSM6Oz}Z=%okdBU;X;qxBfljXehc-!W{JfV;U zS9`;X7Yf&TZGC;}`P|=U6YfvFYc|2=b|AO8L~_j1nuG;gy+R&rUtPbja9`!`e?Lz@ z-rZaCt^UsT#ljJ@9`5OgGrZTS_NThM{n8hvjYlf~F88$ks#c`tB=ESN;|$k^Z#(CT zIi0SS|9G`4!zd@gnf;hoOYz@L@z)nE$yuBm6}xrD+j4pPU;O^__pjMuWUbV2+v1kS zd8>#WhC1bw%qAE3*`Ci+__Hv`(9Pj-Z|}dvVPv`%?fN+-^#Z9$oc&7)YPw+ z%I3wC>*ZIUFI^wQA$`cN_RS`VCv$JDSRdQ5>wwtyyIVPPt@b_pHaYCsU4^bP{bS$t z+?0wF8hthci=iq~%c;%Az)mFMayPvy|l(m{4yzb3uh`{>y3smH!N zdw940zMS2@Sl*s_0hbw{CA?pMFTUV`SGVDcsGWb;n%t^dT=R6(*~urC#T{;4^X8#S zpK-mSYx1e$(vWlR4|bV5TOCup{^tJ0y41O+ca@dxwk?QW(f?lV+9b0r;zxETR5vS} z`rG8|_@eB`f!@s2AfEWdv$n^=`enJUGc&Vm`ATXyD%Q8pu$ufaw)&w#{@Npv+B^R~ zGqbsIbjeYvj_)5s`%4ymW;0dwQONmvI!92R`@!Plt0w#p5GnH5ToZce!;)m_{??OR zlb?OkE4F2*on!X@uG#ZOyPek`2=?qhYx#JtOxE)sKF>aueA(xr=wp|ZXeRvp!m3w~ zu5>-RmelfQ>W(gj`SrOA?)fz)W-Bb2vTB;He4gY^5j*ZkqsY^4Tjp)9X4{$CeCGYt zdFO36-OHN&qv9&%P61gf)=7GiMuhg8I zn-KSA^_=q-x#595m)<@*sy*wUQ@ifJGdjT!-ZXpGNARuBD-K!zvs)vm{Veci(C z=Zno_f5feo=;rXuY<}=d?RwpXyWR$OH>ZkLpLoWatKXk%-tD}Yc0bpgtM@B| zJRVKg-n)!*a`*2Q)jVS7wePdd`S3tCZT33XlGRP3{jG~8PvvD1RD0~czt20m%Z|bN z^y#Kb@$8qkoUej%EL! zFF)$fZ(XxozAxp-x8@dUW!(q=PHfE-jy9Xkdr*I(kZSX}gOlF9_J7}t z0)Ji>ovX*s^3|rXmU${&EM@1o&+C5l`N#UTO1JDjZ8Zp2U|3K%QRUbPt$mLd-c+2% zD85Wj{owD=7@NzIPF|u)vwk`W<=a0!?Va~X>tR8JFsthXY%XIG7r|%B(d&;t!-y&pVGndQfgXa(JlK(IJb&pd<&O&cPfo*NO<8oQ+ ztN;A@^rh@38^?vj;OVt;Eo*~Vzj{?F)NDEMz%+Rp%ZG(C^)Iz>f4OFR++>p9?<~(s zi<-^PUwZ9p*}lp6LGXlA_b*>zXS8LA{P1+wI2Fu2=Tzw<*l<5Am~_Z7^)8sla!S$XTu z!AD_zCq+Wo8GJhXoD7u&%(Y~_SC(5ObpEhsla&wub&As=li@Gp+=jZunPO@auWJe( z4(t?o)8TbP`}0+|58s!UKkoYXxW51W^~bWFZ!V@YGCO}}Ye_q>B`9IqgN}gLH?!{@ zN)n5o7NtDp1m|UqHYfQ#535bJL^!!$Sl)R$=V!s2%Zlv*H&${_PfC^2x_PE`mCpBT zqMFQ?OVo8muO7-@u>4umH}^LO*6pu56(nyld!YlT(U!o*kHUW&1-h(W+g@Z^apmdK zdRNJu2m1q5dL7nToBeP4r+8q+mKQ(&CJ1!?X(}-}w~W0)lYbY>=J>7FEA8t`WFyZ# zWZs;0^+VZ|MT}NU^xUj3FJ+7{lz*Ff@m|8`Y4^^3J`)g9cRWVy>GdTlB3!$29p}s0 z@2~v*HMLx3;#tiL753M9ZXW*dTk0LFs#;U`td1r1%wLMx3tOK_s?9o}>eDT@&-r}y zy${0IUw=B`u)X(F=dA40uX*))zf9})>=dqznA_vPu6yTAVIiwX!*l!3zjCH{mq$8;hlvJEzi2=E z^A?TsU-Z9D*|AG&?YvEP@;=|ve@^*&{KM+yYtHlUKKuLa@8$lhkJ=rXm>E5jn=i}N z#y*VKv^th;$A_o?>WT%jvs`rV>w8(R+<)$K-fi(0cldTCi)tU<{i^=gin~+Ox*Arr z-#p(WvmoVVoL2MZ=RY^tMTOc(O#ZgVW`2F$uOE*m{bPu$OJ8!dxZleB?_-5M34za! zCU`ciYbc-l+4{^^wc}fl26|-a88GdzD?Dyy9=|_ligZS)lZ9B!9G(};+c&?x_vhK$ z%QwW#a`JB+-{?MBLv_AH;QPAWI`xm9&B{-GX4=GhF)SEn9quWYZ#p4fZ6;@>j;`lA|VzkmGsyZ)*8Wamv6UTHp>b@6C!*O7OM z*Xw6_mHoPZfBNoM43py@pPS&(=a_B9`99&x{(PYidQYCT8oMdHYx^sfvP9#O!_38t zSe+U2c22XtJ)MYwzkclQTjL zV%8a7T)6o4&qm-Bb1RXw%bGZ>3wRxkFq--ULrz>3=kFL-Avs zFe_&#^MWwVdDH8Yjo*G&nz2iLlkM%hCsWoamG^B~?3Oj-pr&Ei5|$lIjk}EA3Fw8S zG$~6px@omsy0B8IcG;?e2RD{-mBwgIZ%jL?GgbZVdePs{t5ehJW<}e+DVbt^-u};q z7Dbn`fHxa1wwrD@J`-ha6tQ#_>xs?3*uxUGwXPB`d1${ZF4ak&pg5L_jH;%%UD>yJ#{m!J=u3HR z)_L8{{aa!;dwO-+ZVGh%*QWNX{>+Nn^&D(g4>KdWQZ@wKsbBiQ>TF`)MjqZeYyV`+ zL&fhoJFnVL;eUQktMt{a%|{aN7W1#kFu%&Nb&|(+2bR|nGervc&n5l1DF5z6@{!YJ zS-;+P6(@$>-2Oe1ZJEy8d`a7HYwn*i68*4d!s-(J5~o(y{nO^9ubDg1{(!#Le)j|Q zvl1I--@UpycI*77@0GV&OXb?l=BWHq&$>N!nXci5ERWPwao>;YzM1h&kGAcOU2ahJDO#q*c0;u{5AveJ95CTwkIlPr9_V8NWtvEQnW{waGq z^ZwF9Vy(NU?zn!aFwS%{*Xykn^Rm9}So7|tdqi0MjXg!rO0V5$cMSZtmaF>zpKs4a zZ>8Sp)Y-lwC1;o3meU)r%cZemPd`<`NG45~OiH?}N}R zqb15xeM@))7wB2dor zMaFfvKF|K5t;1d~{;};qX|3P(d$Bin&;I)EoZh7JN1NV6ueoL&!TZd5*5%C3)mOBi z{^maQJaS*pC&z;`*C*9v9DTGR!Ls2~CF4G$<}VX%UgSLSV7qNP-{nE+-q#O)Kl|eK zy6k}EwkF0y>s_WrWpC11#`?yWcet+!Iq^Y}IYfcx0r`cchPq%;kDka6> z@SnP(*faClg@61hzcZ)2#7yzqi#bnXZ7!EGy^(63yMXcZ=h>J3eEIP6@ZsC36LQlg ztT0KP^YP$MX->_g#V6i!R1~~;HM^~z`RJ71Tc>XvYs+>_W|f_J;$Op+%VN`{pKN;i z@AsF>pNk^q9!kC)_^`{7>uOJ%uZvGvPRa^f25rH2Ct?y3UMWn@5L#Rq)F#RpIVm}y z#KCq_d0vI_6Lp@mo12*xW0d+fHdg1&XW1JUY11avddJ)N!G@rO>3s$C!bEp({q}7A`~7zNZ0z^{*%Ff{k?)6UsNRj<6Ac*L?0SH&6_PCE17n%NzlaZdJRub zn2p5SO&;Rbb0m(}`(27yoV%1wv+KIYjBO5TzD99 zX^5=noo&4Q;ex1FCpeV^&Oa_WpU-(R;PLY;_NWU*m;M{*VE#h{tDo8LLkoTH6?z z{_N6?Ibuhq#ymLvRcv|loLcMjyo9TxPFTGh*7j@uAcbr>@x5IM1V;Yk;{W4!8 z?%?Dxajsxw@9j=5okrGlal?{=oQvCEH+x@t@aXLf^MBG`^!t1{?{+hb<=RO--q7d# zJEceKfANfF>CnS-s#fPEbJR@`Z9ew8@Q=u{w&deGf{ahI`L9-gtyY@)`e)I-TlEd~ z(--Z%zs_men`Z|mD5jTe)RfP?5wOu>)`|^>LzvCJ+(=xlExjb7zVFL|Rbf3D7qg_9 zW4HA;eAK_Oy)bf4v(n>5-8+9}8#^&iSNk=s#=Yc{c6RUb{`@$(d;j;8^(u7bv+291 z#@#mJl6}n9{K&TPd1|B8el_Jz2Svkh*2d2Nx9g9a*Z$f1{?oUghfn>M65sgk|0(PG z{#W{&L5P3%)%fMF^!EpU?Y5}N`6wW@V|keMcK3%lBAY#ZSR(H3z4RmTLWG;c0S8Wj zJ2%Q4kDPMLaZ#Vy`2PFVrj&Q0t&*i3UpDUHS$W{Vb!!K2Gh@~Kd%wOizKm_QT$jsv z!{N@+4S(tnz1{U|*T?;~Z>+0t{C+N9E+$|9A1zLD*-_SWyIvbUvplry9IPX1Q8WVd+THMPkTmo2nD%vOK6>|3pxm~>2y=sS~8 z=0E+WGq==k^m?2-Ra@!c&YcQM{I?sv3S6s;5YDtcF~w}QmBdrUt7*dK;gRYfA%OPgSD?eSy{pP_f#K&%e%McXKk2Wf2%(I z*WACG6e3iVHLrj0+Pm-n`zfD)O__W=?e@gNna1T?H9Hjd?Kb`O^yAZ18Qy(4rL{JD zdH?6G{+;_(O{{h0zhzgeYf}$@+WuU0%FJB>Eh6V09##37!tgz_b5GxuY$>rdc?PCN zN2*u8elSHkLR#Ng``MW-H`mTBe*HW}Z{_5z^-Iq7sOF{V6q+ZW>~kzjTWC?-la`#ImmPF8Y0yb9?uJ`lvOcx7%8hZzw-BP;a?EG4JmF zEuFiTGOv_ueO$KH{j7SR+=Uvyd*AwCvvHv$FA_CZO{02-~GzichH^7 z&~*W`o3Q^L#q()r?QeNyxYpZu{MtQnK|6z`+M%xKL;5>a4;kJ#nsVU5Uzy&XCXH9F zE&7k-6X#6blNBc^!XvuVO=V|S(v1EqXMQaR687oZWuaY>7tt!R*14@M)g$osymKaMOH}2MA1q3@v%UkRvw?8(+7^MIpAV_KJeL#Uwe1eA7JH< zR5~ZVD~)SQFUN|$mP`efTrb)D;|rvxz2~i+fAD2Yz|VwjwgzeJpqcy;veSSBY(k zW&EPU{FWV|zqoiB@Risep==u|4mm?ef7awchJA~JR(YSAv#9>vVZoz|_Wo-7T9hcGWHveH z&$@)GJ7%QViifOq-lTPwal#&}?2r0;8;qA`O6qlO{WbG|kIvEZXIJ|5`{&Dtx1@Wg zO`m7CW8K-1Oxtsl>~flB{;mIZFU>no##5?xYDGhcT+@&EYY)}L1aC*2(epl~^>nSy zQZ?1m(yy1}XU$Y@s#lnqb++W|nZNITiiIXk;t^nRIPfqp@0haw)&nJzP6-q|{QSn! zgkAQ>{f6SDF{d~#vZ~w(KIu`Z;o8n%)x_o8-lOzfCGYPtCy7HVW7R+H>fq*^Dq#GP zW9$C13I#bSwhgk3c6O2;RVj;vuY2!2x^luqkEp|Qy`*}*xsTj0;|Qt$m%Jn^e4 z>(tu|=ih1+{O9>o$Mm4Q++>b}TR#VNnK%_T?+mso>~VY5z*BPZ@PpKhx=o&2{=`6hkzqF&Kn z-Z#7zb7MM_te#AKTByBl-J3l32b$_JRrh8%J2EB7be)y(v-4RO+7%^Hvq1Xc!H{*! zjXc*})GuoZJkM-aU3luceo^c3$2AqFO01prg)fBmC3Ka(^!TO|q*=nUQ-CYFDt zO2vf9*Mg2ntnqt(prJzjn}r;cw#`d{@1Mgx6WT8Hx!+rytUuRRdUu~n36so@ls&KC z?b`5o`N2M&-!J3t1ulC$!G3BD)AtWn6E$0S7e?Q3`xANXog7P4cwDZ23~NbVj>&0J zR@3*@k6-SaS#-1EK(Lvd?wWTq&(-X#cvfg?`l@~-(+>0bE2hY=X6>8cqiT3ifYY@$B**ejlIpJRVY`IUHEKeRR(Aw+C3R^*4nW z`}i#Q5r2<$ZTmE zjTb)`9@d|{NTb2)#I+9}=Y_GJd-wO-Zcf?y#wv>dy?M56J^btc+P~@L4$E7$?!o%I ztKKe|#~*$xTr&Cpxt`C_qGi%A?w{%YdVNnw_QuJP6Aw?_Q1-plyuOCcUDrx@1`n#@S3_hIxV@g%FfYq^VcmJY3n)X&40%FqQWxIka{g$nCQHqEqC`+sz;@87?FjR<3>ki&mjccTsQ>!$p9@=4U)*RNiE zag~guoTzc3P3%v3?uEgAr?eib*mfVNNc~t=l=G+m)*B<0%YLgO?yfn`=@I4MZ8axa zJv#X9-e=R-^T*Gx`qgpj!{p}pbp zNoyE2gl;#yo}I(~WxH=o$U$M(8x7kIe0d^PaP;)OJ)hs6PP49`5*>K6>r_}so@?sn zifJGFg8sX%PT!tqt#*z-^!@#euQAzQ-+j+NA3xu2f8sxtU7c&P&dKN2dD*P9IiJaG zQ^BKhskBp<-?q}Jt53;4P$5sCs#a=Clf2u-hJH5=#%4wz#-heUx*9L9RRvhF-4va% zmH%kJk6;j&dEuU-#oXKLdzAK0Ik-|`jzz|cbLItRZZ6aIUoG{Yp?UG{lLm#7mlqbi zx?%5oo3|_!zm@KosdInziH69WO11lus{htr{BKk5s(6lX zj^fFc^1B}>3Y!1U-|xkEHO}*y?}K0QAKpFmxT&zfC!;UOS8|QuRh`#1`IDLg?*5d! zWO=x3GONn>>!Q>D@=r|46*_x#t>3D1Us*4?o+~}1zUt41z>HmjmRDUT%~GBrt}HuA zgip6@iMPu}k&V4Uzpb7-2W32VapGMW;a`9D(6Uy+O|nMS^Udch`S)_=FZTxLW#Y~Z z?58wEcQtH2!F0q=c9U$}>ixMV?#tEJRm5rU|2wrMIVr&1M0JsKyM|HN1f~PboZ>>u zBCX0MdRI;;S+M+?R-wbab=*0PrQMfS-B4KRkl2w|GmqolN0DXiSwM5 zMxUzLF6!#m9yhLBzsL5ln)w4qu`?@g@;=Y<5k0)|U%y1Xx&Hb3fB$~$GI}^cx#-k) zBW=Z-uK)Q(XZSb&n{dVGWbOvxk2j6pIEq%eA53+qE=_We`T6Caj9o#MVX1x`<_ zi3q4zu+i@Pq>btN4^$q_R=AKM;`PHm%f5s~=1BujEoWqnkk-O`UMs?!;x=}7S*I9n zj_KK9#@AK6({lt8cwJc{h2=#>M4= zzYQ2F-o9P6S2ow!?aG|JvgcMj$?9MAtt>R3J*mjeczf8D)6c)_ub*GFs-CMwdSf*Y z&;E&Tqze8WD!8{tb5WJyKRZMDOexp;UR~pSw)bCarj*S3q!IkP`TLn*R^|}p9 zTF7|JY1!WVYtOxz3Dp~q9ev8EyoOzH_{8 zg{am4a6TZ;Qt$EZmCn_3^9v{HtVw0B`OC!q;Qs$ssqP1fa#?e{4&FHHys@HGe@pGR z?f&vr@03>UoV%oTcE9q;W2u>r0ao)fj)Z39{+JxF-u=_l3&##cAKIuYB|D4%$@Pn> zhTBqNo9kN`BE;NN+b4I59ana}Y0(zR9dX0AwrWX$N4x?mCj5#?Gs*}5PxZVh0q*1W&d|as#WK8s_EV^-6=J9-9(dnbw}m5GDXH!OU%Ej zb*O5=rS!`J@;4^*)yJFWuU|7O_Kw+0dF|H?9~N^=Vb1buS6s-%Iy-6sr^Mc+y>`)6 zz1%x5=HCCe&DQ??(~ya*MfyG4m9EGz%{LBw(DiS%!pb)J#7{>{G-KP7{`C~?xO#VA zPHj-#`?=o(|9{@1rE=*+iNiGUyj;Qj+=**+Z`B>$85;d$pYEM0CHlAPm11uz#obnl zxvjKHw`*(b>)T0kXKJG@E-J>|R=RgfDI$7;1?TMWe$JvNVRJjw*Bo_Z%KRMN{{Ke) zsO=iALES+@VJ&aw*q!zFmfNqf$e#}l7E zMZM6L^jANxik_{Dy!ht&yk+y_&%gSWv7z8s*@M%oKBve`ulQ$eIo*Zp{KFpGMbXO` zuFUn=wd&uw^~H~Z=Eq(>_^!H@HT+t5G?71iUA>ms8DZucpTxo2^25u}3tO~ecU`>6`E2(QHMQuIb5?zqUio41_h-#JmIxMy?|ADx_uQo# zpN1sGINv1}+d7`u`oCp)XCb^`_9Z7-v5HN?+o#+#%y8+R!tV2Bs-4cetX~_-zOKFa z`NN+dze+^~`Auq>>kn@zT$#48q@nQW;RjWV+Rm2h*Dzj6o-)^Ud-dC`fdazI`k9xB z*f&;IzC0!wr2pXfnTT>X1AE7bpQTj7|CHRRJU{*V^7Zxme*gIL`uN&}Ll$P8?@t+j z=2_IwKXVl$SLwFh^Zd1r&tJ&@P9a+9U`~eMYSw)<3DWOAb;`_p8nL6h{>dzD%f_Gi zc@HLUyD>5B-3cGzm?Vkb#C{jI)PIl8npf5RO#bS$#yVbIt06Dn_||QnDrxQ=+Gh?& z^gZS_+_B1h*7Arj{ybI%nS}ZWYj0eu(sj?;qEKhDNBl|Jm#~_Z71in|)D8C+++law zv+ob+B(*({Y;E@c{_*4c)`&y@L+e-k+vile=kf8WI*&E?12Q}s>H?kNY@tAs5MhBr#Rd?UCjkR#l&B6ydazU=NR zXO7tEdY?}UnRK_WrssCY@e7|^eko?!xjk@iW>|VExKkvYn!T zzn8c2+v+Oqj_n6mw%$=!H8WZ^VRGMFKB0}<9&em#C$wtD7YsdTekdg+ay3;xYN{yjcEOxlpM((!(i?1YuBc}}Z$Hkupn4{b8Pcv)CoS-^U> zyuqE5cjAJ?PVakZ+0%XY`Q6@4Ex&@_#$^hf`fOPrH@_=xSBOhQadW#>(2T@MGpE-- z4BESwD{*6I*X{Io0@s}mzVh8}r#<85uQxxA?G?zIzkIjy*7=89E9*-|H@|2ri(>L) z->kIz^;a2*PX}+c-S|DTaE2J)m;AC1yY=74%U9p}U0_~jd2?TK&>U(-4B(9!R1FaJ!NUHMIdmPWBxB%lSXpd^{E$$&mcIsPX;D>)%yG9D>%H>}s5_`rItPp!EVqAFmzS&bVE2 z&ieQ9c5Bk*-Z{OylM99sf9g~FXW!Nn>^4aR23q?6);N>o&SBj-TFJBEERsPj(PrxKCY_58`jo`?kq_t`*_1JvWHlM@>`3)>=0n64MD&4OCRRn>lHx@@`F!tp_GOtUUh5KhSC4T_b@An@=p8s#N7o z>bC^kFYw`$qCFZl2+^aTXs5dyI+PHH5q^onMtU5lsJ?ub&Dxc54Ba0W!d;K%Q?rNT+ zuVDW6GfqBj71j+|Z&g3%U){ z8|Rw8a>r%8-13{Nchq$6{(dg>`?e=NA4OiCo4uRwwV0yysRPO@9?weXT0H+j-Tq{$ z!rLkRfiGv?x^tHMyXNgK3#N$0Ez^72L(=&9MW^-JEZ9&z>F(zwv70lYBmDCTe$Aw=db-m-zd&V&q%jqqCRX znwytjbS<);m+Nnrb8&D&rgCmk+vAPbb?&t-U3L0mR{lcAHPbJ57*uZBK0n~;2XUDb z_X2+!Ree>=SaC}`gGK*dVtQlsz4EK4w1qX#c$=$T*MBOyHe*7?WsUPUCeFMY^YL)h zq@R~wYqKvB3|ly_u}_0z`l*d&=Qmx-N&hI|_sHv!Q)JGm@i^u=pTnlEon1c}C3fo0 z)L+21Zbnu632vSSLyh0++~-&e!u&TIf77wKvLSBMvSjOflUFdunHk+|`C!x;Eynu& zMWDwKHBT{P;cmD2HxKg3)K7j%A# zcwJe(XqV{Olv=w*9QT_{8TRj5@g(VJQS3AmfiS_#Hy$^67zjBut82erW9#ex@zFLP zLno*HTW3BB+}^gdeUhfA>>RVZrE-sTu4LCY@7U(_zBz8{<;}UB7P+B9+z;n%>z@2O zH!`t4H0;ha(TK3fsZ+P7PTk$>T@x$jbyIq}zV@|mSIo$`}7Xy0mDBt#p}yHGJgx4(LZ-W^r~fY!}d3I8sbd&Av`*V1s(iJx*CY&n-b zous3_O<>xygHn^sJnHvt`SW>~+Q(8O!%b7j_K<*`~KQ^WdFpLg^H1iPt?M1 z&amA3=8eOwYbi}kj!B25V;=omP+#%?>&yK9|0OThRGF+<5m;6&6L+uCr~dVaTS*HS zlo`%^%W}Nb=QfYY{wtO}yOLC5E;nlY){NHP65UjHOsznxyY72Z|Awz8nm*|+Hkr&i z|F_{X5k#x^yJ$0U;q7mSi1J*r~fOv{-01w z{P~@K=JR;F|9^h``jzg#>Gaerl@$%Ag)bUuKW_Q=MeF?j8;q+jRQwgvS~sOoAdjOi z`NWP#1xK}K>+js$uJrfU#h_9V6^ZqZOox`tkZGIRa^sfA|FT_6lnpkX{W$kIYk%GQ z#D9w~)wlY-6->KeHkId7JV(}4o#;jeEg!p@Rf)^Co&ElN_i_Jh)m^um;?BIt?8w#h zXAnAZ#w1T+lc2Um+B%hI`V${lcUC+p+n8*!F8|8oyN6%D=6b#)$Ee%rPd5MGchN^r z+q{4C!D&%i{64!c8+KN1nkh2JCg9avS5M8wrA0!aP7-VDmjyl%`@yu^XY+2pA7bBT zw~5{`adX?SfyS|l~ zv-oUzzdrZle%pO@wSRtVv0s$knY(WLEq=2F8pbcaUh`P6;ksGXmDlb4_Uf_QPgSp0 z$vmkx^|``?l3M#@6~&45=a(&8t=lNPRKDW+#y6D{HH@TvJeEGWWvF~=-ovX$T5JU) zgACL}Wwqz6yS(^rW$ez{sWMtyZohT6P`OsUW%HfH3a!o6Has^EP5;^2A0Hx@3M#!_`=Q>%LE`>%3! zbxraWsasisifIH5p1AakXzd-@fm7PB8bU2!8GcuDiB=8@{Ai_Pv}{=YL%8!oLItuP@rB_YPRDw|{CW#CUUR z)Dg!R@ejY%vYq!;H7*tI^|)|RIL zdmjjIXMXzk@#W|1U*D;IHg9o{u*Le7kB{uvdO5TG+wvdv5_9+ell@t~>tF1T^4xl1 z@$!wv_wp|My;ryH(jL)u>6NxKuYOo1tlg1Z@1C@!>a3|^`sU0tAN18?T$Z-H+4Jx8 zYd7A^Cu+eVCL04U8tlJ)WGA0*>C_uxC#&VV1n&gAU3^)S_f*2o`X9T0&i^Of8gj<} zXPi%Bc>cYbs?wl>MTzyLWit2nOqWcIjuKn4!1wIRg+JIzGGFhl(U^MX$vr0vy?Ikw z1^ahumd`MXU!3^See?e2EjD3i{_fb#tX#}L_uZNIPo?(Gbqo)i^7nQ8P39&|f%=K@Np6nB} zFWRF1Y)bmM#?L0{f6|ud%!69ZE8`tnyoWHDj_{@?m z%fp*RcV7D_V;LOAVlTBhg&`|PKwyVVz1zf@6Y};8o>#swN1{*S*(<|EoUToim&G2j zKT_DUg7?qQWzw~iLbPu7PB>S~ui~*_d0~U6)Z(vq)&|{v|MqbEa^Cs;lg)PgE4a4g zs^_OCol_Wj4o;G8OJ?%*yrgkK?eZtZT-|ooo1ZSpdh&(O(%Z=&x=u7+;@@83)er7$ z=`vVYuh4(lK-O*Iw*w+iE?>}goHDaD=Df=J)Z7DG9ZJ-1yoe~=U=*^eS?h_#yBX4l zzwdpvreRj)lo)fzx|a9zcdSyfKioNcd#jFmoeP9=g%D}(k2E5myUQBtyq-pru;EKspxs>O}>`;i?T0YebNf+S6nKT{Asd- z&%FiiC5K)yX_{|}_`4})%ZW*eo}K1u2V1*cI1i~v2wx2RW!_~mXIZF$Q~DO$dj0j; zLX($V4vtx@75MbrGKo&vp1q29u4S=U&-(KI#PfUX**1}>ljj{X)?SorxN`Nz5^?YA zpUdnf)LjqOx#!`!d_}$PjX$@GHZ-!EdMvp1f;B9Tb?*VeKSJ}~_g-0=VRLI|>t~(& zDHrA`ZJB)W%O0P)nkgB(3O=4WX%(BjCH!l7eRV}`)r-!OO#3JEg#wj7KD*MUd40ag z>bBKloD7d#bPR&GOnP{HW3kqw&~&X>Bi|DXySo0Autq8@3jgxl!z;RCbNyb!_eu&y zA##z5tp}$b*_spoX8QHx`nD68@5K9D4R{`OlJ9hD;7t+d8YYp+F-J}2a5Vbx{4P+QesyZg=1a@-^EcK$jj!f!6n0-| zRB>dz=A!uv&UXlK?V1-r9cj{(+3HdF#C)Zq?S?usc);V)tF1`5EVXj!UlxLpCr#)Q%;`jO9+uO5V7MQg^pC)>&e)f;Et^dul zt?xZqwApd7(&5)#?S>bZX*qQGkXS@{TeT-;u01&(9&qxO?xp*n{a_ zdMR$%&Zj?fwO?d#&+ZYLS$0k3?;(w?^LJD)p2u@`l34x8PZiHByiyFFyxw4?o6L-TYG8lg+MDmw*S`*UxM0D} z1kVo~5p0o1KWB-zn)n#Fxd|*Tx}05UjE1jgS92qTawEXs+*QaGucX2%EnbVg1pr1oN#B)x)dv}ZE)H#=K z1k9{tN}m5KdrIk+#LLIW+1u>f_q+bbr(a+Cr~AjthsAVFvwS>tuhZ0~iIT=AJVIvi z1t-l|_IT!ZrmIblXY)4+|9@Hgf5y(ZXZn<1uKoYz z-^Wo$J0zlnb|)$p`uxrlVyVylyp~naBj0HH>?6AhPiimdir;8(^RBb{>k7*lN8i=`e|Og5Yo8@2 z@qOH$E@JC^Nwmi8fpHD@3L)b_7rHVy7hW|g74ods)?QkW$-n5O&#kGx zPPUIML#?)auW_jti|B}+FQhsrbq-_7H}M6krYc!aVytEzs5DDhbCWYL;8|z1x88pn zTaCoW2|sk!JQ9AY%jnE%aCVc*L;k?9XH$BnHu+c=6ohb|oV!G@@6Iz$#+}WIpKR~U zH*!~Ec|B?K@z(}-XS5_%3(uTAr7ku4_JPtG6ULTP$NqS zc_)h3mrdZU$otj(_|I!O^&N*8*CjOly*l^9jp@tl6Ey$+`ug;H`Fj8TbuqusuKN%? zsp<0Mu)b-}de-bQuKmA#?pup{-*%}nTJhK+yee&dN{HGejJIB|2{2KW*V(q!U{QK5(bcOcrlPa$lEh@327{qpPcwXGO&F@(o6g3 z{eO&`)9$=0dGt)Q;s3XUw8)F0;VM`C3d7&{2{C)vpFRDV>EzZQ!gf1WNGm_}_z`X7 z(L8yf<|(zKXMVg}^ed(K#md>wV)EtYa+ps|uGvmS65 z$13WwhKVfVe96N9D<{A#^UV`|ZFM{TY^SDXnU#fCG^T|aCT%V8oZdOP%0k14GgkcL zJ)=oiJ<1-$B+6a1b=|0WOGn(SuIp$^>f9*S^QZPFY*y0gubSI(Ri*TG*}7X?92=$| z*qi0GC&WOn-uFa@3B#@Of_n<78xquf4@R{6_IYIR>a0$R=$aBRsi|<{o2-jAEmKmL z1}`&76;7Wu{o%U;gKd>t*2&yFuwfnFO3#{V!C;GJ&Wg8Zy`1>!#ZE5%e;oo!EBq%} z-+gDwnqI^D`DViD|DFrkc2yKv+D1=yJE} zEfWjn?@uVazjJ$D=k~bxeRegqF~%H5JUshP#fqE_S;Z}W%OiT(EEDNSeYdKEOFq7- zw34|0bC2})4eLI;ZHPMS>AZ(k_j}T>4)NTp3s-wMd%8sbTlSEzuylp8f&<5?jvg81 zQ^D#*pE@&mzXnfP$noFzV0}r|Dw6Iv|4Dk!RZq|aUVbgnNiPZnQg{iGM> zmOGE$Y~+2a7{ye(@|UdRqmv0)GoP4lQRIG+6Cw4=n=!oJ$%Vb1F<0qfk{wH_{e_u~ z3W8CgOBXzw#INZ7e(Rj~U+&!N;eGq+-t}EU>(1G$#OP*Z&c8n8yHV~O;g775qSH6L znz*egyGq*NvHzhc{i5#)(uZX0)hAq4-Se@2o3wVg5_gb_j$3+w)Xi?I{>O)Zg(TK5 z%uM`{p4I5dsb|hB&}XmxHK+OeqQC7ie(R*nG}&K<%Wv@$FSMH>7L|CwdDHR6&Gmu% z3bW#m++5|Xx_pj_N=PYZjCf$AMS7Bu1iRWzHKz2d^PSuBOWdo()_DF(k-a7KSZd4W zUkh~VUvElbmzpXgPf^z5(?_yAMmlMR$i<;S$rMS9{%?V zbDBReA1vhEfO;$?m1t=lh|X?#V}nTv7r0}1Elixd7iJUny$!-MpH&H^ec zW`9^cIfHHE20;tXu3yZ7b_eTZ)dV-3h*`Jm@VvUP1v{hiio{eU)cYE>YZA(2`qx?% zoa>0nwz%@_TW8Pr58EH?N^catI=x%7OdD(yf1FpU0KTmOEkcFkF7 z^$E5fQ;P416lwq0$!(Y~GxPJ0|E#uYMo*``sXtWbqi~?LoUf7T6hp`NcgwwUZchEl z_&_pm$8)!zoL(CyHSb*;7UT9@{+-EjE2eLcA4zu`*R6fnx~J;Uf$Pz#QYx<}@7cV@ z@0$7h9*z?SUv3Xu$ME#T+0XtP)Nh{pwdK+h#!te9_4lqVG%Rl=b#O?nS-xGqTUV_Ltl+S`%F}W z7fSbO{8uMav_i6i&*Sg=S7u&orKFYj&Wp$8Eo>O&v*bZ@( zwh3>YY}{nZ_?lIc@3=;neJtPD8)T~ae&UA3OIC2Rr}Dk=TNL&>hx1qUlH1pQ<{f0Ct?Kc)91-ut{}A*?6#K7oSbHq%xvbpYEJL{n#?Ku*n>x9+}~yl&2msoiIVk8Bqg)b0MllRmd;k+W%s&Z>@!9lWIy)y`{uHijTR0_)Rp3WWm*Zn!elAl>(W>fz z{lS|giy9^e&r_cMCTCe@x_MQLinjf7!&3V;*Lv2IhM#UVOqieTVfBGQ{(htQLW`$er$88dO_tV0~ z75OhWFEM>xKXaG$SH4p>Wz0h?9(O%C7GIT``Xe{I(&*!*(=8>dSr5jP2Jhr@j#}Ym^DVlyOmr-U`zVTIwp-%DVj7y5AUS2CnZ(LzL z=gtnH#glfhO={I#_fYcS$`)2(>E@YC(jC?rT_0o)vFBad+YlKfs5MnPqk4P({l9-c z{MpbZ*gL87{5%0SNn0@n~Sl-Y(gAuANV9K66jWyHj^MaN5h1ttvW)yd%U;p7N|TOpEq~2f|2SCI zMO5>`-*Lp_Prujk%9~s7o@#$7aQ>S6H`nf&c+q5w^))4y62rOL?vgVl zO?IuEeWRF-bp~fklZ8>yn=AhxdzDG>+N_TZJ@{?1!n5WGrw64=0uQyEt?t&hj8chQ zVQFn?KI`s|TBRp4_b#gLVe(16xQ2P7joZa~ZrLfV(_YwyyL}c+vAe908h18SlBxEO z)y^a80xE~)bTi~{Xui~mXcV0M{}3bF^4 zlrO9I{B!!SPtt&0E<}j2z};X&`3l!VDu+F@Ha+&(?1 z-WW`nRlgurCoOODntka{zf0|~H)?5%W?v%Ib0(K3rO^F%Lu`~*mukd>;2mjcYHijA zpXN`Qs5kr2sekIWzux_P`Zxb|MDHt?PuXtYIj%PFu-LDCIIqW5@xzr9D#mJRk2vB? z_{)8F_I!Wh-_BjTv#ps$?@RZd<9n-njvbz+F_Ztr$I}n%H(e@OneODb!s=kJYKhqb ziNy~riZoO&8C$9@w3?Ng^h(Z?`Do&V8+S#O`&pv&=B;C$@2>ePk-gj~v!zjK!WHg@ z&MKk2i^5(PUQEmsNs=g1DR2<>w{3cDcu~`F9+#HcS?1IQ(+duqP^;B23b=jIX4A?! z7G0sTf`v=xIb}9D*V{BY>rcLT@U|G=gCiMdgc?+g4xZh8+b}fQa>LiQM&{ewFV<{u zKHpfI-Lkjw+wu16%lGF#;gP-0wQIFYfwG6a=}M+fb0gn`NtqKbUe?@Qrt*g^hfjTm zw)%}N%atD7TzQaHl$pI?GIyk+j=;LF%^Ye1&y%?}7PU?|!)V`kzAU!htp@-)fxQH)dlp+UbVTNzT(Aq(V^jq z&5M*bi^A3%eVdeI@y%uVinGfu$%oB#+oQN$Y=cEYB#YOHK9QeC<&UWL9bjvn_gqlV z#bV_&Pg|GPc&GJFTkdw*e7o?Ya6|oxb<;PP-0eO#^}!6wsYli*Y^yskqs4Z{d;e!v zUnIG7Z~ic`c&V;&^UBe%IW0-u_S%zXtiH>&JZkY{gG~-os-i;p_*M$<4-q;#*XP*j z_GL>W*8S|AcYo>kGWA2&HjQ^?rR237n5))rI{?YYyo zEm5m?__*PQ*QZlEJH@A+7LD_Ip-~_d)Dvj--a!AeQv8}DCmJ{B<%MjVC(ktT{H#3A z&j~BI1qJH5`n0}l=$u*B%u~I7Pk^H4mnG)$FYX>*9zVaD&oVlWxh6H)+4}t6cwW{Q zKFd2#+B>WabY_?0W3W+(P^g>waf8N79Truy2QCwi)UzEpbM2-<)dvgCPiN)-SFAT= zn!j)s=SRWdcS{2L0y#R35|SPX-2Arji*s08%!f-qx;4sYCZDN|eo%L8=2^@4 ztHs@N?|yo?G3|W+{`x~K_1}MdU%#Gz^@~pxAA@ec$@sA;bLo>l$%AskE)raN z`cbOL%c;SMH!OVIi>h+Yy;8hiJM;Q+{`>dV?~ps%U|K(|q0?&fH(!^m65o$bGauiY zBsZN~YLA%sq(xUm4VDyrJlhrLn0`l7%OxXWqRxqj-+sK`_Ik(lb-UO9`t{@A&zF}U zmx)~N@7utC$uiJxlf=6d4e|!Mhsx~=>&3f|c%~UkJ($r~x~c0>amP-k;zKt)3Ka}y zyr1gP(b=4scKTL|#?>uz8%q=xb~1B0S?}Ze*L7;j)d_wRB4qp>cW>1+DeZ4AY?RUP zZQtjxNawgA>oyzB54OHqO*toXtbABH?cYU#O*x*vMKF8q%>o^Kza)H$sb91XE-HCpy70nlT`x_sI|nwqwsuG+UJbFjda$-Fx6>x6 zvBb;kq4@;X;KlC!Zx)|8CsrFI)?A;akQb+KT*NX%kHNKfN7VjPfj`-P+}L^k=C`}Q z^VdhKnZIH23=*#2bh1Y3W^rnq{$xij&zWh_zvn4P)$?0OFe&#O-Qn3a`G*>}>Jj6) z@u%F%PM(`lP#{wC^U#A^eG3Q_!`7BQ8}-*LP3v4paQ*a*iWOwpcOHFj4qU zN$rcZY6oAHtks5@bimLgZL@M{8RkybaAbJq^=rt#EiC+Fs0TxAn;bjgW^yFZv~%%q%~5 z3qCB24UxW`^+5djYR8@DF9yw3R^9M3e6ny%wn$cs{ucJ<(hR*UP80Pf==;oW{a>-) z^Sb4ts~T^g=YER(me96FVK(pae=n|OoDxkCuHV$S>966g(j!;&W|XXcJYQBu_~y;} zD@JR)H$2~Ix;>sXRdRPL!`f)UP{XOW9cKPx6NzQAp8ntxoBZ461NkO*E-&A2yRWV? zMtOR~>(gHs=4|lJwp#UMRjS_CU!SJWZd+S(D*C2JUq5Ta*EX-*hAXTp-@2ye?ugiT zMSA_lQ(DWPUD@;TP}76fgyb;Gmt_y`E{f0F@^M}LF2$KPLd(`RmQPW#@cwmr-?9H+ z^ExTt;>T=fe{<*B|GsI5*qu_j`_CcP6f2WXa_}6Vz~JSsm+s-YKdJW6DB~ zZQl|8WB<=nCfnvWPfwk)Z_{R>j+6V+_6Tv>MQASG+4|*wm_V?7=%otQ*5tnIR6}o} z^^Ba;H90CQ%m-xlo!n`sZqn=boM?`L#n<4mR^`RLKcf)y7zD}H_`J?81sAhZ99>M-T|B8%w z{g>v8Hs-th{@~)H7!@5<{3cLgW#aw6|GvDuJ$-A{+h3v2>LRzE+E68^;4yu@;JL5s z1mDGXef*UE>C<%U&HSo1zuor!6R*$NQR;qtUV}-8Y4+8V>y8&0i1wcLP5gA_*T2fX z_wV&qFMrnkex9Y%ZU??MRi5dV&TNYvTph$hLO)+w`tMoDgq^}a>UQUet>1ntEPIMi zu)#czoxuxdyxSqlDzqf%M0xtr#|QrhTxV$HU9sSPX7H82TlPEr&oEc?e$?V{=1(m9 zlKO>xOp(1xe;S!YWQ4BQY?qhTNSb2$h*#(J@4dV`4s}Y$esTP8YB11;507Cd=8^N5a_ zPJ`Q?N%=y%nmc(FoL>LFo8>jNPk!bV(};cby`t-a_g#tc|0B5V+myKQ@O94% zO-`6*NGmxZ{unvQs%?8_7KCp$ye%|6-mP(I_dLwMs!BblTx${+pfxH?xkrn5djKAAD_2y0hzHM^ z`nE#2Zu8qO>*MF!{r#2t_EdDU(cF%XV^=*tm9Kw4rSIUmwWkc%iG5=|m~6^lo|Q9a z@yQgI%etLzFEYzdS+5dm;dZ=pkvXc}b7tiyix&4iMis6z4bI$}`e(`Ko?}UZ%n~kt zJqrWe{M$}!KJrIJSuN#O$B%^{>Z3k%2!C>qx_swH3G?QqhSw&{P__IuQSHc|wcZ7C zos&K%S2}N%KbY$OFXW}mh7Ua)Q6hg`Il8t^+9VM=JHukbz8aZ$r3pEq+3Z)Z7+IX3 z8QyD_AkoL$9BPtE1_h z=)qV|p0a@C_*4bXV=|>~woiB*viIArG>?3=WZ~^1m-Ynz>kShQEy%WsnOd>g@V0hF z$jh@PH+~#a?{(aEc*(-dvyXjLRHloixF*jNtG|CdTK;ugpb@vN$yVl~+SFicPM3MT zi+&_r;_TeRz0b&IUhKgO^xVvRmo#^r8cu@LJrIBIB z|H~;`+&T}gIdI)8C+cI+1O>mO=Ql5St!RyiFgDdYks92;=#QLBZyM*mveyYo&xA}| zR!)9cdvZeknHQ?s3(8&h`uW7ClrB&4INj9|yKTCGqvtX)*T*L$7M4DZ;(n=mv*6;B zbS~%QtfxC~%vt+ZIDTSmQv2k8sq@@6nY`dInysWaC3wq$19&uU3w4iCFpb*Un0tLd3d zA8me=T%WZ4gw({9uEA?Gb2v6P=49}nQ8;sGO+~H9y<0cz1eTt-as1PJ1sBm;qvGqU z4K2LvDEtK;*#6f{OiAceE9kC?(hEV-_Msf|7N;UciI|dx1T%Dq!xNdd4K%) zW%}bL^U1UH>mrrrH5}_+a>#sx>0(a36N+}16!*oyFKs<;{qyFG$%@+TGM37gx+eS@R0<8kE3vy03-Q0Nad1&^Ei?X63J5pS2%I1IHC3J45aJ_2njwzf8%05@mh=^;oWEC#@m*#ZY z_Uq;!tM6|5e)GW*>BE&v3Qx>%oY3QvpTQkvSk|JGmgo9swd$jQ6P_0Q4_;;q-M;5& zU-aF@Jlv<8W3hVM*U4KB$o$ZL=3l(BnDgp1*9Ud?e0Bbd@Y+9nobcuD#S84r3Va^I z0uQIn-tzHNeTskkKA$KK6D7NAC$kStnK`NG-xMu*mSfUWTH|!rU+hd(G0I(FkmvW0 z*XQw0*~u~48orM-BweFbb=COQE^WE#x$)QQwB#T2pC`{d%v3iy#9cnu`bVa!{=e8e zjyE3g9pZn)_hU}E{{4MSw>C+x{a-8N=&Ury_oLdS3scwBgk;sv+~OtnfGcR)9p!th ztM+A>i=}SLp1o)7|I^RUYhMzyxmW&W-P0X1%8R1jyTx1Xy0bZeE8t;uLg}jplT*cu z@(tHNX|fhc&N^+nY44sY%zpL4I{eCE)y;ss|^t>x-_xNfX&dOP(?Q^w*_?{78pE*Q5xUMFSh+3-H^#>4%; zKM8gP*Ur#7*vYf}_(jhRd?$_-zgaG2Woe!d^7Kon80)>2%TJ1~cV-JI}7T8KCk_{Jl=Kf4x?7 zP{1@UPtn;P7P@uoxBN<2l{Vv_f6RVmqyG>GfaU9lkuheSY|XT=!j@yBie!&TP13G9`-LvQo#Y@ATH#vX{Nf-{`i?%*#9@ z8$8$p1-2Bn^hrDjV>|v*w*R$T0 za^dqmpjpolIa9kbSETCB;eZ9{Nm2PiOIDkGvP%7}{rLKnO>;CZF#E^+WY|>0@oVEc z>DnK0r|YV||9f~_OyJ>cmZFF3vs8BJ&DUUf>G5-7K>xlTtJ|%2YGw(1m^l5sisaJL z<9g{e%3ig?-ygiPyu5i)jDDUk`;rb*)wCE}_cX5gOgo?I*NaAMO}^uOVb1;ZwLuH5 zrZ2W^XuYWaWa_i-&?2wTw>)f0Z#pY)cu;%EONHsI+T;rhAF-ECJ8Zw*JNUt>V-NcG zaJ4*m=a4!Lz+;iToy z_uKCKx6$ZC_lC80b2|RjJ1=`>!W6=r@-|UqPZh&S=h8*4k}jX!LX&^%E`O!;c!#US zpUz#@88a4r5am4*D7m|*)#bFSyyA-)vAeHcF60r6U;I^H-vk{{Nd>zWI~g@%3RIP3HGc zOb++;+TIf4H^m{L>XBpn%p+UkDtp#x)ff~VOujdjJ?T!2;kUP@-PH%F|*e~_7 zSvfuVslj(e=Z06Y>BXjgu9e|gPXcba`y4*f`l-iUUh?Ia^JxoQK0kkR~fu&Dkb1g`75SIpbhf`$(Z#_)kmY zZht0nLM5{!S`BSmDmf%m0j&cTN>pUA2)qrmw9J5Z{7Ku*Z#kL{GNY)HHYcl zj5i#&k67;VpSx|*HvgRhiYK2Wzcy$2d$H?d(hKdK9GQ;~8K1l#D0w=CH+S}{7Z2BL zs`>DuLbCt%%um~wpMPIhSMmS0&Fq?p-o%P49Q{(yW##W?*FQXDc#PXXOy+YC=KN}ci=<7{2_xkb)B0PnAS=TI76L`I_m#-}A`!a_#@uf@it-s#>{Q23}2i*I9HM~@+=k2=c ze$?}L^9)1F@~hK!8f?>PyP>4jdiz>dX5!I~bx&PlZI1j}c|9j4(`wqh1@^h?tj=lW zscyJ((r($*oRk}J%lofhbnD>Wcx?CDUzexf|MzE)(uz6TANsJcbj}ZnUgY{Y;hx71 z%SY36KEAFINIA4J@zSN8)6ZN!9Uxn%8g*QxUOD~IdVjIBCzGFaJpX*r%A+a#QJ622 z>>-Eddl5#*-k$W{Y@+-r^32p-E1Y(I4h~G2;^FDv%)ft+v!d|n=G8O#{&Cf<^D5&P z=r+`tz{?ddRo|~-(gekwTax|vGRjV#HY0o^6C3Ad!(-9X>*aqnTTXCgxqOmojZ)s~ zmd89vYEtzc73by}^M3REwa9hSv&t*0Pwxz$8R>aHW~!m5k@V$K~<8 z>k+)--!G9}}p z;a#@32Ik8QuGpICxyxuD4_&_WEfeeaq&K}E#3hwwf|eP|)ZgC!`CR&?M3ooIO7E`q zF5ll$ZeRb~==_xUunMDDPZjtk2I%ll?2KJLb*PcHK8=JKj?Q`l`D|Gw0@6EhD z^N!Bwn#Q+wj`N{2H;m`3Uo%}L;?TM48{4LylK&CcYTfQ6zNYYX=+gexi@W~x7Dqqs zXf&2dQOo5|c`tFIBYZ|${aLx5G9xdI?QGU-?&#b~T$EHX)#k_EzAulnthK71n6xnS z&-{1$9N({o_7Yp4L-`%tsZ(Cfd9ug##5}Lh4c0|X+s-7{9ZKEUJn69Y$7zpd&kj&9 z`1Wv7_W$>1%4h%d5}!3yLrTJjK}@N;Q?Q>$!DQ-WhC}WrwbdA($eTM%KA}|4Ex7O; zL(rEv4vBQHbA86KDqq$WF|Mx7U=!YOWR3^lLjFGrrRGyukGC>iUXt-?#s(Sn^kW8U zg)(l>&iAwNSZ(G3WlITZ?oZO_}qXL@sVARC>NB@Ko@H z8nvJCD(+(9)<^kX{FuADOD0{ywkEwnM87g_j*$1r zWjj)@x>b@Z$skUa@lVT=w3>CNlEcm!}_+{PIq`G2R>F= zv8KnUSHnfRgLlC$uVu5(d&|uG(B%@OndpB|bEcsJ*M{9H^Vrjmc$}AgdfFpqUgrU} z$+Oj?uFl*4_e{OKytO~4;0oW9Gxx-ODP`GVC1iNhOM|JgXVI=R;)fN~8INr|b^Bpk z+E3O>|0&D53KqBgEs*ncyEH{CTk>*n`RX6>VYj9ww1xT|KI=WDv+CCWrPr7Ao&CCY z&&s^C8pRzS?$>X=A72;!&}`FES*uO5cMKz?PF}b)uS@p!m!Ov!Q|g(%eJb+b#aAH} zwC~=E!^a+q&&*SKKf9&!WcxAaMO?>N#&{x)?4s@TyqApqW%jwsI}`g{ ztc*@P`c|F$;pM~6zx%cKRvemE&m^hQeR<;=H^F^j!hLYno@LI2{T^r~5D zdiotAKX0b~eW>SG-MeerqP{1btR|j9S*$E}o3hygG(rp6KLv={hN&%THu%}iTtC_8 zYLl*y&~oXo*%xnzr>{4uH@$qd?Ci3{jt8wb7J95bGDqsho(Bd}uB(h^S?KcAZje>o zt$6W+`>md|XFolnifr5^jS!uJpe^*KutIq$C^k|~aq#Y%;$5kKK-{}3q`Ydbep}W7-cpT6Enq2y)DvTwl zGi+YNQx}nf+SJ1e(-&^3_RvsmT9x(7U3u!ORMsPRB+ks0o3g5uzw+Ul>uaKVxwe1Z zAlxsacrQp!Af)<)nZpVGjK^-f4=X*{&Z}SeH|s)Voj&8C=BG+7&95g0gqOs!CM|ta z$&>rc{a$^1;^UiVPTsKNPJWyB>`BJ_36p&nzhU0gc~VXPPtXU!Af}6UzSWB_-QiqZ zd%}Q!-AlfU`zjanuK%8NJ~QRQJrhqSn=O?o*3b9+`S|d0mObl#+WPv=+C_)_PS!Uih-htoFnhJgC&%9k z0u@|~R?gD>6Ub=m@-IQgIQnKth?WNJ(%t?aAVH-+uV{oYGdr*Bd8pEh|?H`gSlnO*!*N->YEb*@wx zeh?S4`N_d1C%WlT6h~LR{xy@F3I0zn=;SatIb7A7#21hpxU@~TL;A@KtIh@exo;uM)`DN&$UMnmMRl3&o;Qpe(V>?_Ls{dWJ^t1`7k~{4A z&iB@Yd6S$x&b4rGo%fQdY{};M@3-iBON9m7?Dn(5D_3@uZzwt$F>}UC^VnGZW>1^s zbVpHvW1@SnbmYdKD>+{<)8442T>nIUg4Z;Y&i`}smL7KJSG2gX&P!hUXdQp+#zlKp z7A@uUI}o$;p-xqeU#SSoXQM-EVQq3U0Y^GJ9wu<4?{Yi2a7IP-mR51Uvue66W(hZ^ zom+VG@+DT&zOzT⁢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 kYoEIenq99?AW_Q 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 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index 58c4b528f05..39f8b9d4541 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)})}function notificationEventCallback(e,t){firePushCallback({action:t.action,data:t.notification.data,tag:t.notification.tag,type:e},t.notification.data.jwt)}function firePushCallback(e,t){delete e.data.jwt,0===Object.keys(e.data).length&&e.data.constructor===Object&&delete e.data,fetch("/api/notify.html5/callback",{method:"POST",headers:new Headers({"Content-Type":"application/json",Authorization:"Bearer "+t}),body:JSON.stringify(e)})}var precacheConfig=[["/","6a6bea0a1c39a50df5e5d8fc87925e55"],["/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-7a72f4dcf2a1d5e04094ef807478614d.js","88a41ba0e723e4ea89fa12431d7e5823"],["/static/frontend-77a461848fe2a94da4e26a103bd6f814.html","0c8ddb1765d0133272522a44e4a8f86e"],["/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|manifest.json)).)*$"],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)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t).then(function(e){firePushCallback({type:"received",tag:t.tag,data:t.data},t.data.jwt)})))}),self.addEventListener("notificationclick",function(e){var t;notificationEventCallback("clicked",e),e.notification.close(),e.notification.data&&e.notification.data.url&&(t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var a,n;for(a=0;aPhG)YIT?N-;jR$R6LHtS{lCW^G)eVzQQ2~1&m#>-toN1I@E3&X@iDer(8ke*3EQ zy|>n;j{hHM=UM#A5BE#BUUN8||9as`^XuLgt=9i1>K@##y*c?-~zwdndP!) z&MxvfR+QWP_`c48GufrDYAXJ}-2C`_qjtuv;O=+!ztX=Ss|*ci+bC1(mOeMQU4Q!1 zTNgiW-?mQX|5L73lcV*!w+25?f52~YFQUFOq-Wky$;)aNXp*|lhfdrZK^g$-2=K>-UFb+trJJ88pwFi2|E zoEI%>N_Oj(uPCwYN?PD0yiS=bbH&zaG0tp>Gm6{FHuuiri8wOlOwg(n4d(;u%UpPD zyeoB_%3^%E&!#FSs<9a$HsgYT2tBA=q zy=Rf%SPIz0PG4HZRe54Y*W@`%1G%)g7SC}%P~vge;%w!%z@rk18+#Y0wJgk?cqU0R zbJ0w?oQ#@mw{p*aD}%)Vm25Nevz8i5ym*Nyiq490{By#3Zu0XY+&T+o{vVHmXS!yDF&n zeCkM3QjDC{%@JJe|L$0$An#%gWsap`OpANNj&=pE-DL2%@X$MFUDbvKA>PX-X*`nP z@)Ak+lsLAt=i5^K5JMrsWTn8sV?}d0wkSR^oW|C!(YK=Ob8o_y5XC5&6&{fpk0+;h z6icYD@V&G}c+W>>f_GR{q=f4hOJ(eM|RO!?P5m%Arnad3OGU9wRpT`Ia zF1y(8vR5;$c=NQ@6PXjA&kA5PQZHO0Sm(vE%gZq7V}HtC*3dO#*@;pfEQXFgoRc{c zCoT8%V3^$y(6Fgq<&E;0FxC8Pmp1rk=J?OBZhGCaA*9$*NUw;sQbus6_Sy}#)oXq( zt(8a&`qNk6oNDT9X_%T^5SdE04aGg}&~kjHTYeZH`!uxlPi`X2v0y5^A7QO_sL`2mX@ zxvEc3WS>~IEdBBQu(U!$yYD-L_A4kx|JqX*tNEk0%04+FZrhV1%crsJuc>LSF@1TQ zZ;5(Jw4Bb)nc*6?8521V$_nONl)RtrzwFrO%7j<`vQKy3o2xH?3Inq zEA+gs{JGJtc3|S-o%`xj&DPILeBLC+er5BAJFnetF5b28s_WLktM-dC`9GzfyItAt z7_TO7UHa&Uh0gZ*uYHTQ%1Y%2-u_onn$XaC&S!0--EsM%cj4bBe%`I5{krbL;XgCp zE#DCR_I69;pPrlx_N&W!zCZmr_qnfCWkmVin19FALR)88v7Xy#(P#BG}n)!YAYD94a?ESqd^G9ie$({oF1(GqJidZXp zDg_+xg)+8DCTm{j^j@w11&jxzCVAk zWbA}Zkd%7si67Q_~sMId2h754K6d^D$*_galGa0r6(eptA&-? zotGb)nV2S=a^HPP%fk-~Uhhsnm%r}!qnWpb|LV?D$P+5gi&qo#-w5t#6kF+Ct9$0p`RAGEjrgCQ zU+~!RjQ-8N^-JP!%v`OP+iNoQ_n*+cTA^RxKTk{8*x;BS%*`D8_~!TJ*CcP`8NKka zlKu1L-%mTS6S1$Ef0ga@zW(^dn*F)h*Y=+V)4E?eFpV{Oi@- zb4y#hTS8}Cn)FJsqTO8m?%DR{og7D1HPUMxlis^rE7$mTJg(=?{niTq(8uroa)xc( zJIA8r>yN*Em)~w|YbdRGZ{{|wl>6PmqW)XT-DWn~7V@>%pFi+h9%DXNZ)03ib#!xa zt7}ZWW&hoz(%|lRUxV-sN{2ZA-%gt{>%(MW{@($uJ!d9PTEAz+O{KqFZ9$3HI;!fq{|BQFCPa7MHFfafB DXL?i+ literal 2285 zcmb2|=HO^_-x|)uT%1}|mYJLyU!Gr-om!-qRm`w7B75@fZK8j*jg|+V&~s%}_z@L4 z+4GLiY_m?=x*q$S?Q%AHDz`*dPP&k{?c2ZaaT6wmMXi04VwD_i!g25T&i-P?{L2Sd zY|dS|#@u*z)XhyR-DPixKie7LeIft$s?Ul)t~A}<@|9yzf5G*ijw#ave(&b*Gh1`y z*Guu)+jjB4J6|7l`0WeRh?s-9)zPnxOCi{tVGs-?*sgvTyxSE>%U&8xuraNN6YUIo&JmXw|_gZMfmPsS1GLx z4gcQl<2YGkSFdQ_u!*_q@M?us3*v4(t=MyS)hsFHje*-TzsvU=cYox>9Hv{FuXXL| z7W4OdQMW>;`dq!nrvGOP)9#!vOTT|Q`r15h2g|~RZ}nt%)yvQO>woX_vTYqtpYU3} zj;%`CyKY;bpM8n%+t&N}0Upu+w#V=OQpa%7$@-Jtn_7WWZuevVJ^tDquRPuIE7Mwu zrZVMQ7k9BfHDWiNQDnG(*QaH1FP17zRp?ltrRU$fmI=I(vnv&@%!dRoV z<%zy7MFGaprYg)muK%_DUXRS~mPcb>5j?eb#b<4T>9 za%bm^^qb-hn>R#-`-uuJ(J=AaZ7aMOrM@J#m+NXS}l&W2_%H9nqk-@@qgBuc!%k;uZGQF>{47P zc`{?+jDxqlgq;{?H(Y7hv|sIwsE*mxjO~|Nx_sMC&hgOnaq7Op;VGeE$gKn zdw-r(;bS?qEeZP{-p`2D58zww+E{o_P|3t2<-mr+Y2swYxn-qg1|ak~`%f^rqh_`EJ^tfH?`PmPQn@HENdV ztt_vV{U-Bab;Q9tuk+NcgJ#^>aPr9R57sMut{htA!t_$|+3v|xR|NA4ZG6s}xO2ru zw?d&x&8R6E6A#r1o@n;4{k;0+e)F=gbyc!lYyWq(ym|5Y-SViz`JdY*4}aXGtZrCt z^5fgp^C!YLC%$p0a@r<(G3rKY@1@0jGX?%|@*Ye6pZGH=uQ|YFTjky0dGdGKSFz?) z|DEy0e~0xYv91krCaZ#b7gyPYu}>;UDq0f9KHvVg)~gAbS3f1~tN(LOx|*+zdqwEt zhi_NUpZA{W@$CnPW>@>~6?7C>rCfaao$9Yod7TT_2&7)<|Df6Xo=x;dpX$McH^xTR zZ0FdjebRnkT$dg8;fja)wtZhOJHA-f`qjVI;A@~sef*MuTMZ{_zHjIiQ0i z(7~TSi+88L+o^bEifC3{*5clRCmHYM;%?quoql8Ig2RkoyJFb?YE*|^Z(p{id{tYz z$=kqxI0g(BbSyR*}#$Hev@(_itnVvm*K0mt;`=MDrs;NQ#ly8T3J z?ZnWt1}_rp&h!W0Sl^#}NT<%N{6+j#_G9g@e%W!P?X_96yH4-_P1Vre8C9z1Hd^#m zJzSV7aJTEyzO}iLKlif7wtS8K{oAeZUqV5ZOy!nR`GprxZ;PBN>$2kB|9!bfV_Qu2 ze3D-%dAB2rxuU01#PMP{W1D1Rf#?=~^^pHcmAP$>T39fSN z$=0?!Z{fXkMP}w|@kPgy*B{%M_^{~74fmARk3W`t{2hL8f9?O>>HiLVo&V9`=grdA zSD(L?eEPR7)845&=YOT@t4kJ%R7-f zPVH}&-k)0b^LTKn!mQ(;#4iLttSxw|xt%fiUFW)oYU`I3O}%vO-}dvfeV4wjug!Mn zX3Uo!7Ac<(`SJH5cDob^4;Y{yy6_X33mtpZogXC9CaHug}i==~8&U&DefX zw`^_o>O7cv^UlAjg3^b|xl^|lU8(B2|MIVA{r`uFR!)`7w{FKx-Z6XP zTi>qVh1Zq&&6N&L=lb+PjFtOlY~Y+-RsW_Pf4#r3t)ckO3qQ9|U-o||KQ-JE?$)!3 zwwPaIzT~0f{yX31+HK!=Tx~n+bFtSuc7C0=>-4Mi=^N%Hu1g4tZ~o8N$G0KOQiOp401n!CXaE2J 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),c=1;c6Vvyn#NXrZ&mzc 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 literal 31529 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 diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 38667131117..e99fe69c8e7 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 85c93d71a4ccbb9b090dd983e6d6bdfa197f706c..20a48a1f014d0d43a1eb7c60b844615ac0be5471 100644 GIT binary patch delta 12115 zcmZ2>l>N&gc6Rx04vxdxyBgWIvNJkts+V@3^ejH}Tc7BGRg8_Bo?K;U+p$Tdf5*ah z|0(JD{b>eK4wG}Z9g=rT3vCrq`gZ*d|L*vrpDW5k%^4-U-+Rp#3DaG&n7OLiGz6Us`A*RKC|_S^bbdp0|+e{Uztf8^txb)D};TQko+ z_Gvi3FY*J=cf*Z;Tdb}H%t^DJ%6qe1>R{}d!)Ny&V9fq$^*^F%-?BdY@MR7&J|2G{ zE%mg|@!Hz;&K7SUN7ZegQM*)ICUDxEgqA|>5=)oqk`J|H>a!=V_;5XFW={!MRQDgA zs!vmc);+meEn?BMeOHUksm0s-5;$Y|C1fh*olDy>U1IAc>4s*$6R9`)Hrd^m?|k&+ zhw$8`mhbi#27P;ehDCE)g6H0EkykGMTrziw=JLct=9@a$y{dyQ7-YX>o&G{u^5fn7 z3&O9~z1z35=x31U)XO=-^=H|4Jh5$?*}?zCU{Bz??vH`n7W*o1krPZi`9mxAS^lM` zAF}3h1f5L`5}X?JGRW|JonE(P$ZgG|wSwUVbLM%J1Wz@HONn2!XR?}Vh;pFvQ}@cd zZf-Z%%ZfC(y}iaGGCN_VbGht)vp;VS=HLHY_Tl#4`@i=0*1!HcZBBy8`pY}&tL^Pt z%`QBd-G7#|{oRkBGY#u3b@*FSZ$9R)o_lB0BaMCgJsl@3P|TA6MXb&It%F~Y$ftV0d$IjRdp4}*7IE${N;R?WIoo%XQ@Hz+ z@6`lewR6jAY;@I17G8Ot9j&-C^YT%TSFsrzwA7O&w%cX=J(BwPt%%|61r$_uT;K$`RHI#$gdWFm8uHdqbx;p8b{G){| zhSOHxl$2he^|9r!)y5@L?77Y?%D-RomAyBYSJsKshvQs*VD{??GFB}Yj(&Wv5mx17 zXY%WKOG|%k?sC;0r_*LLbT0Sk`l;l$u!;JcrQNKw`gu$F+?4Ik=_kzH+9v$^^wfKP zv>VGN_Wj`sfB94Tk4?*oir&i=%9Yw#aL4Y03ETd!iapUcjUE{An4XxozCg|2dyCaM z;~KLEGSbltf|jfK)Mrgv%sT&kp>%Eaa=rsu&G9_R{oI#NSg76hxKk8&MPCquwJkO;z(> z)0Uafjc@sK6?!l^xfeaYKKDWQ+>1QdlsQu0hTjs^TsEW3xYYgV-fE8e&tVxew)ePf z++i&K`D1b1T7w|IcJAK_&l(i;??x~r7TP~Zv{z)aS^j;utX%!e<|$7WC>#4k?|GMZ zs=_5P?eNbJT%J$0Uia=iVYz0u&I;)t3$_JsX*>TU{kWxSl1bPzHQxp4qSM@21439A zSzQ0B_aaPd^-K4@cbC6}fB$D!Q&F$A`JwLyt;@d49y|X+_wUX6} z+Ltprwm76ZJ*b^oq&I8fd;Ybxe+nHQy6m-6GtD@BA#Kxv>Bp7qCtX|dNA-t5;@soH8#Z=|=9r}52})iEDS(w}Bt^0=j8 z81JmM%ul0a$13gO(D=r(rg`grY3U#Pz{65IY3gaFwTJQ(k{ z4_VAyK0V_4!=xMT=1K?4i_a;=|2iY~)Yx2XuJ7+Fu_CQJ@$O2-Z&$DTx-tE+JF|8# z>jjHCqaS+P>=;%b?^jffez2{qLudJNJC4q6+xrvvyr|l_w7Y&PFGEsA7pu9* zg!pU!LJsL~?bmrzo09lWnLAnj0+3R}JG@?+}U2P%dyyTzaQ$RAddaAzu2I`qb1qrnrNIdz|#{gOG?-PaLNlq~dC zZd7uJ?0NOf(4#P-xw?6BifP$H-_wRU*=hG#wk~(`wTPY@qt{;Gv@L}($RYOKgL;+5 zs|WHgE_vms^ixGsK&DiDnndmHvwf2B(Hd!0lcO@@v|VP*J@bK2YxnHZ^3Ctg&o1S? zqCD5|@b%+0JQi+~Ub`(wR+}3V+|2fSMt~7(0n2L{eWux-;paUAUaUUHQm3HwsY3o^ z=Mlcb35Wem&V1#2lI-@H|O5Wr{%uy z&&_ZSWq+IbL6^6l`K#c`$z_gfpL{e-V_i~eZaIPF%5Pbw?JaYhuho8hCG%G~`$qWY zPp7z-C0W(3WcqZ)^h1-U_WsrhwLBNYmtM@&(aAVJ%`)C?;o^`L6WT2q+?D>;#O?iA zUVZ6LfqlJK`hs;AjTA~UpJ^;CY?J$XThZ3{LE=Y_C^y~El)^R3x9!l1`M06UGX7e; zrP~#4wdPa%bR`xCUo300S}*Ff_v|~dlM57EeCPT0_x$>8B+R;PO_k`&W43%LiW4UA zmPR^oZZX-$`z^DB&(V2@`W0>)H_e2QKaK~rT(4^g*5BDuFMp@~TZX3ep0pU-z=e)anJA6UPs+fjv3)jY8bd_uCk34KwU1N0V*0s2@ z0#`A0iw2F?mp`7Yx^c38*2DjkYeF`MPSsSLt=0BF!iU*?pG5lq%)&CO^FbxE4n{Ax z*q*#Rv83nYJ-NNECM69Ho&nd3B$um;2g+p`FJn~e@9$kQ`Qf4S*HWuj2-Yx{%r`vG z$MZa(v@7qh;I}RxZ_}G`Z4x>h+xE50oRKZ3C!l`mrb?TgN$ZUxh0HIG)L#peQ~y{u zCr0=3$>md=Qjh#fV^Ry7c`>Nh|H{+}=?p>MhYof{NI#5So;**I5}*Es6%o2?6N66TzW+h?I&^~oi1@5jmU>t(;KRXh>RvF2pK*XIR2TT;JY zy884bYmRK^%x|iHyZRRy8GqD?owI0p{lb}L8)rSgyysumGSMafnfC9wBYI|DvHsNy zGjw@WU9PPXsSKQua!RqY_mJ%Yn@Qg^ZpfcetQKOeZnu0>=c;SF%s^<>`aouOgXxub zZXFO>X#4AnJJ*YSl_G~Kd8DqEOV)pW=qxzbSjvT2u#fq^|G`)B0xDA&RW`ok_FbT} zFJ@-_dr>xNr3;stj#)okWt+DAxTtk^-rURcH+jc>aTMRs6l?G6%bM!6wd*XG&`~>VGMg**{ryRnU~kkd;{zK4$h-@P~(Y&2auA8@+yeSEEGI+`HP$ zX}sQ@3gT7@9I9+hkqQrAwO{?NE1{iw&F{=_%UBl)|KC!3n!n|pGWGl{ zI>X%~-t4-w$SnUK87p+nc7ZK7Gya)%n}s3%@Vkzdkr# z+ix4^bA^4ctqY@Hv=vOPs*?~>eOf5?YS$8hTbslL%F8PE>TF-r*wPSN-)?SyH)7Gd z3s(0{`K2!gNPU^M|8m|u(-(G!gl{a(lQ|q_S(fL!#qWG;*z_Gd+cebsxg$N+eLn1L z>Gn85?&-F-wXQ`ix0kM3v^{@&%KP2ypDr#o+<#2>=i%JfHf*eZOZ8-`Hk&W1{Nu zjrTMrMQ~nLG3yuiTr=gFO4*i!Dq&GRLejUta89_lZg=%V{#P51Y(omaoPI)_c(x^QZwc}NT6(z?KaD@$C%_bIkc%6$7I^IF_V`sb4GbAnN_l}Rq$h`b>XomJA&%@gO$$TytmGIu88Y(6~D9Bw128k7Q1Cx^U2Nd zo;;Vq#(Q?VTudixssAi2o3w>*mq_#5C8uK?cKs1%kG&{&%R2uCbM@W4H|@GXx2uz% zx7yw03_E}4?vJ*;mxR)j`?oB}d*6GG-S(ori~b&``ZOLPF5R~^uQFLuRXR36z zz}1MUJFwjSXN*cj?*4rz#ANTkzYyeP6}Cv2yGDEU8itm=sjG9A{CkugyUV&jcWbTW zy=8x-HWuuiwS2mep}1iJ^EG4EEqWInw_7dmlnwonoB6@u^eZ+U2GO{>&HUVKD;L$a zvL(q_zA>7=X??wf)#O+)Q=17{j_nIfxdi1m%#h^l2=Q>u7Ghn+F-K{eMVQGi$;~GA zeMis4IVr7XO;4S7aM8b0Gj4hIs0IJAcM?y}@A3{jJGYVh@$*W5%@?8FwndH6dy8`7>K8XEOfIkf^F@38 zk3*~9$W3`8CZrzleZ!px>lRj?5j?a#?yCRqmK?{6y0Re(MF%g$&wkj?p;<3jB@ zwZq~fFS-t7W)$UR#;<&GYf1dMmGKvs>V5s#Zu0&EYr*;-KX$Lu6-Wq)y)@g^S^Gs) zdWl@;>_c{K)7xbWH>heXnziY8eW|>sHOr|v3!48NQJuJZ=ATph?=3m4Qj=VfP+7ln z?gYKWlbN00Rceg+x?iQdwVC^z@5Ec5ZVN$6Gds^UGL1_^R4r|Tw2oK*{=wC$xA^Jb z0`Yj)kS~{5j2?W8E>GI2d%UwR@BUN&UD}08DV#m5ZxZHeCv4LU`0%XS;8gvT+}`?6 zzrXMPu}sz8)1lk9_4SF(NU3@Tqd5imU*Zi3`1cfdvED-Dx6;NTR-QT-|mHTz$^+R0& z8>VIjtre?Z7qw}t+(*8JkE~PUHcER>Q-~_jt*fsPueg3qmP0HqqIdps?>6t2{h8O( z6Ml4uG-^*Q4pI4gV(FQ~fBvlM=I)wd7PfG?ZWf1F@>l1rGS|%W79ZAET@}aesAwC% z@Z;8%&e7aCbIPMvsCCNy=k@b?uetb|>BS{0pPz0!VpreXMUG|>Xu;jDS z?lt~1b8^#!%z58LbiZg=*LKaNIsD}1HxDeHEjPVTRl`&y|9^IXR7TV>7XAs2l^0hO z2o$$3u8`nfwRncNu=4Hcw+=JP)!z%-RhW|MBCLPP{+4>0=3J>8>WM#1=FgW-*DXqn z`1X_SX!)^L|1X!~EUx}J{8?VkuJQ*<(CVwlE92Prl&1+lRbv~K|QH070RVk)@Hq1_a`r0Z_%u` zhb~^OnK$pV$ALfH0yQf4P9!cC*j9g5`;E};hsY|x=gF25=(oT>4^@)ER>kbD`ow8fJr@OSYZ6FRxtV$orstspA^%hr5pT9WR~PnD&0B7khuURh@a0 zYqDddjB&k|Qco{e;0&F>?KfB7Jd>NLdhLR#Rc&-~>i65%L(quI(9iO(ncU3C+S&@DZ&aMxANB|jsiKK)ps+ut8M$3*3`**k$} zOSmi&G!}o@@UrU4mkS&2=$?pGepAeFMR7-_>_Y~tbu5y{oUE;Hp9^%dU@lCr_gl)( za%c*laR5WYhVR=}y1mJ)v;E!i|M`-8Y?BYqlPcZRdH1#b>%7PYr++KW?t~Q|%)Oxz zpB!K)w?KC7lne&@r}S+?(H> z#o^S^w4h~~aA1G3^~L2OQs%CaE&mri{@C)?-QF(X{+s3Me2j$=YiC7kU7d4PbD?u= z?8cfH^L_7bB%1wPobS8b^T7)C_M@HCO}>Bow{!dZ`fp|xyc_psc1>d3wEf8EOM1d3 zll1JCU!7Xd(P*RDy=s@o=b(P0^bQY8_prseXP?GIeFTIxsXOWV$; zvyaGXUykLP=pAo9!MkTeRKU^_?y!VwW>wo)@z(!*axV2a-)eqwRgZHs*-E%;gVXb7 zq;^>Ukx`deY-lCGwr{qVF3Z*@K4AXy)4pDZV|Oll^wZf5|j`?f;)`X5wWdAp`v- z4qnGK;{I{`*oSb&r@=u}qO0#umKkS*J5+Boet3GO8z09jU zuif6%-aK*R*Hgw-<~{XEJ&Rx1{ZgEAlc_r8(_z_<&*$9fl-HV)f8^XxX}3;ygVM$e z8uh!)Y*I3&J@GUZ`Y5@)W8#Td`y`(F*)A))kyq97d!kF2&aqurw&%B8uH13J(?Qc< zVk$#Q=*)@jlQn|#_${5Il=_mRR`v1JPhz~#HItP|*hg_jzy!I&5~Xr>bv%-6cW<1& zaR2|oGfe;aQh)tZOqViAul(YYc5s%I(ccdz&WJ2|-l?`+^ZdT+n%$1+mUDI$C>-1Q zzcI|VSo^itp0mAcWCNZFWCy!y{;QYoEd2CUp52J=mQhjnLY?1XeSfE|3zy!t?=ELS z+vNHW{bn1!*9 zZQmQFO~~Xmw>~sYvddKH^Ud7#w#@1NH9 zg;x!qDGDk3SsIkO3a9y+Z+87qw7+(DQGrs+y(YeEokt%P%;Wu*v_+PSS^w$eU0D;j zZr5b5i4mJ$njB_Z|9Myai|&JWdygJlwd`%vQ_j18Rvv9id(yV_`OAw;$#cF6UEa}s z>!gQMZ?jfQhtnac+bO(%8DuNV%dT-oo9#aQ)@NnXykjS(1=sA~aMNY2we^`Fp#inl zd;cBQxVG5z%(YuAXTR*yvR<|F$E26LOj0^$X&ipMr{A&l+{6F!{t{cf>Q63upv<-C zfAGGVb)RKlFa(4|72M>wsOKmCSJP7d`@)|`w(OU_`$j`dJ@@=(2}v!^Et-9c`8q2$ z6s)M3Slgofh-J(2o*L%v(6_o7o3kVjzA*Fnw&M2pCr7rG{jM}SdpS6yY?J*R(~bVU zUsp80@$}#l{uR!b`2B1)OW5faamBp)osZnUNH`W}y3LD7h=0klzDV@U^>i2Kvwy^O z7fWlkFUc-^x_tASVzcg&;8jUHS?k_j`@1S)>g1liJ4L*%*k`_X-}S0~O^llE1OD9` zGS}Zb?$$T+gYfCr1pWE?-JATxzv`~2dNgUt%Pg0kwdOu;)3zK@I9#~o*jxQK9&DHH zd~v9MtiHJB{;zJGg)uy=2iH4%xO9B}iivzzC%IhB>XcoVF*(9w|M_z*-*>w&UMQBw zyr8Niu;wT0jm8_bj~HE4H5(#7vOVAI@qU(GyW_G4tKRCKep4K`Mr%6v{uL#sPX~SR zs{0$jq}UsqofT7h{N<^KN4{MCapT%D+X*&rWN&8>#n6F?QB+u4NnBuiuFNT&lI(Ev^3P zXU%E1q)iMv6+_Kg&3I$@Rt9fpUdSUiRpV&*=WKyruRmF(B&`%vs^>MF#PGm;O?`D; zj=BD~H;wkEUd0~2Q@=vTqVq)djkv8Rl+QVHhZ(Hh?a0#+oGZNlZC$f* z_pIRbum^VBvs~wGn%-DAU;2;=ci44?5Vy*8%t3Cf`8`2yTmNV}R9xR&uNvX?;_Yma zjJ_=oq8{5_f5xIa&3E%;laJ;vMCDGe@0}3FEPt_!E92ANuQw8S15Y_|6>T}X`1Ztv z=w~isIcKt7YDyQczFV8@ckR=*)7OlyICkzf+^!icWo&&bA$VWur&l*GzMMT>pKtzL zx!Q_v51(HAU=jD}PxIq%LhX5865R9a#diFjx5a6qX0hnm4;xFGCqI05MBQ-j@l~?s z-Okqci+7YreTb0BX?_sBgDJnQFVX#{JGc938+*?~8KE}|Vk%3uiq3spZ1GO$wd@@| zFX8)VJMG=hd_K32H%PB2<#Mo?>4w>764##G?UL_XpxU1o!1=8=yRv9))S9U(zrGya znpGdPx+nYRzlU419*SykRQ`DKtMq`)QZG5Xe-GK-h-QahFs`WByU-|n+k&hQ8L#&( zbkvaA@vyJwY}h)#WcG|R+3eoW`S0d^KhHR$dz9+Dhem7_TgW*>zpPR66^>o>FrYjVsBAJmAQ!Vw#cWr&`Hhqj_|% za-qIeSmFbhf5Cf{xuqR+q$ZzAxDjW2XZ4z-Yv;D^%y)PC{DtdIHB1;XBAuO8?)4x zmV2F>mcC>CaOqpU&gu`_^L5H@?YZ0A*eLn`F~h&FC9Cf+-D|N4-F9-n%LBB zbDw|@QYq%?NGVVeqUSpkH&Y3 zzheCR?_Hk#Uf}9o2D?+!w@E1H3+lwb@?P7xZ{qa_>z}T1o*puBdhSI=#rlV4w?c$c zoD0-j*A~t?+ui(w@!#`<)88mxxb?rbQjR~{!)N+WW;MBOiynP?t-1e8oxuI;8$!N6 zZr=5yMgR5t+vm@!z1Umjb>Cvn*9lgi9@yAR*ZQn})9!xq_rW*$@8izs&HLM*Zf|?| zzwLjczU{M%wU5oc#cI#DP(#J(#Dm}I_4R*$PAq-><;(GqSXD!-7RJUHme z$R(qc8(I;6^?Wz`^PaPplt1U0)ou`4_*w494T+vfqOy7ojoNWlJ#B@|pC>;#peND# zKJh=(wf(xU+GhAX^_y1=ky zLfZw-`h5wP^@380+%q<6T6!>ceu$p2Z~4vhExVl=G+WkgY?-!CWNEs@ytFSL{=ToA zYW%CawSJ-To+So1gHPx6y=44dQe58jtyUoCK-u+u`^}f8gx$Wq;&-)`a><0{G5y>f z7cYHSeQ1B!jb<%_+V-;fQ$KTbzqw#!*Tc89=cVG2_efuROwro2iH(%O#H+M?0+s1$><4=!rUhR~6?A9>p{14NkFUo>1n3(EM_PFl% zAwBI_!>egQF5kZ2{CWDcYDYZh+OCWDKX!b18-0s?CikzD^1X94L(TJVXBqsRvhaY= z)QeAEOWdB)t{B@rIr2k&nap8{w9CPF7zXU6ZtFwdxGebj zM@I5hWEHbLM- z6VBWY>HM$$E`Lo3$K71*r3FjGiU*~Gw4!Jr_yxm4C zdDXjZPqTM7oNR44neTnT!2QDRN^8c#kM)*w@3gMi%NI;?36PGnb6^bsJQRCw|jA^d`3D=5CJ7|NGr$ zq^7?4cKCE2&rV17nbFso8jD+YJgv@~=(<|}P0`~SJjEZ~?o5B%{PC?+$@*_i@9J+( z{8n;5&?jGfr@4Rn(VeNQpDmd-TjyLsDVyx8g=r2Kr(cu#BjmBN`;+!OkyE>NMTs#n zI<|F5|8?&dnfmbGt^R2*6?7Cj-kr#NI{zf2QPWF_gNu5tZaIDwT$E9|UPq|4v)JI0 znvd{i#J4_~ddayZE(M&;fiIiv7?yY6%vt+(ftuox zl9R9WD{C)0UoWuv7}U^|y6r)+Wjdqa?ghm^j~>=NJn_&3cBM&f2fWrzjK9i$cyf}o z+DhAZ9KVDFuKr4|Ub5!Zq932S*#GZ5a#3}+Lq?oS*rHc$8vaYdpZx8V%YHFkuaB9 z7K@Z;mIm8I2Btome&;rGXLU@l&kYq5XES!APp3X^BADxOV*==@WVnvDfDy6dYwzu=79oE;U+I|yBKK??D@1N_& zS-$mVc5l48tl1l89MG{?bvbg|%xU`463TneF+E(y)N0M>C(ZZz$z*kP?_lRyNpr*3 z%jTam-T#I6@a=y~*RuxBkFKy>tnliSAcwkC{%fYwsv^~w>+e7NXeP5MSVJu@FJM8f z>C2*Yv;PQ5V!vKaa+%9I@$U- z#O==9=U=i8aUT}s%9PZ5{$te&93_USKEk`pc}@Ao*qLPWH1 z@|V0EIgdZ}o0d&ozLD{Az_tsvzrW>P+!fCx{B6n6a|#zj#Kjc?Y1u3|8eQ|iRW@ZPTTdXf{|-u=yyTRkHV?TcV}IG zX8YIb%7-@1Ir^o~SMu_$|L}wTjsbH^;IegZO{e=`6>EFJzj5>0uSfir`A95LKDcku ztH(Q>PI)*kiur$~UQ$_N!h?5j3{m# zWw%vVTjcLL`Cj6|tu3-Sd0cx9>k#+%j|mTE{d6yz z!&BPe5ngKe>g?)!tDKh3d@LNeBzeV~$IJKd)yxq8|8VI#N2SAC^wS)^PW3#kydYKj zm%W%O+x^KO*{4qr3_bHes$>EHQ%W0Y+PNn=;j;Fe~Y8;#rNOI`I=6Dy#EHyU$w}2^R0xloi}oqpU_!9yRf^#Ei_|Ij;y=%w=k}wy5HnxFfgh; zywP#_t8&RCe%>i7PVnfQ)c-o$>T13CFFq5wbBc%4yu3D_H@U3+bc21zyd2qQL2t8< zH6`Y<<`&v=rFU-k{-I@9rN+pvqkh;R&G=2&{6dQhAqlww-6Bt3iVGXhdiqK_!rS-6 zZn45PW1V{&nTN}8)l&kyJP8aC&38E4N! z*Vkv_7$epf{Ozo7ew|ugP*>x|^>t2o&*8RZrSnDvfu0q_mS1be=dLZ zTU~QGH6r60_Z_BCjnB`F?=roxQQvo}SoZdZOlueZ6pM2o=V@rwh1E}cdHrl0Pu<=a zZ=ofN^!`2N=qrA)E8)aTwcp>4`7PuyJ-Vq-Vp_oF8@k~a-c`xvvZ`aZtwgMCQ-+4oK{n#lo(y{ z?5llhymrar=G3o7b7M-@Jm)=Lf0OgI`1g0ZE2hi(yjr)Lv+b^CuZEB5tj?p}pZ8fs z&(}+MbRf~{)TE?6980~kK2?A3YJPJ=xBAlQzPm;0hyN_tZm+}lt=%;Ed&$B7S2gWV ziJY)-C_39}@@0LY<-QPgvz>Z}JbyD!d9Ze)V(1!22D>trb4v;)v#qoD`&8K0m_NVX zQ~Y}0%Cd6z?&|N~J_U+5ZlA9CvwXw+Lv2MT7hONRN$HMgS>H2P_4i(nx#fhU7=Ea2 zUUbT1Vb|`Uynw>h&OamFcfaDg>9jIP+GYL6brNp1<@y&z&pEC z)|_uQKl07Cz9Yb??{rTz}I!y)d`(51;w=T~T+uc2}1jmSSRN&y*-}@d*Fgx+F=BZS&PzX$RkY z{os)^^KOJ?aZVohV*7xUiSr&8+xai#Nj0{WJi4@U_WnhC_UG=H%sVCbgl3p!(v zsRc!QbE@u5>b;>QvZ$l;sPjU#5NV^P8ZlSa?CA!3L~n*{nAC8$Ua5Wat4OQa3#WRj z1p7oLN!VS~N}E41cA4+t3z;u|?)`Bk*q=Y;?sBGwy2Adr#*U4O}UK(T( zp?*x_{fm+fk?dycuJ!u2?OtF1?315Ywza6++7({sUM!Qb<5~ZqRenEzfBP5nn=Hb` z+47(Ge>uFb7I&Q5FtbYGuTtiLkBJu_vHs1xd+z%r(aZB!jYi75TL}pJ+H$GiZf3)q$*7>J} zcyx2$O7<2i7}#8@zSLcAIVthc-R9lbC*J3(f3+a&%)6VMk=$DU6qUBWOv`y$n(HX0 zUU7c;mZFHxD=!2}uYW!JWcCCRw}YjJrrus&Uw`*;Zr|$GStYLWcm2K!er;Wqt}DfL zZIz;D`oi<`u21?fHD5~n@ZS@xoccUV-XH3j`H-(FS@1$}=c&V;qVrq$R~)^uyZu^; z<-grEIf?Vz!c*DO<*Fhl`^%kKUa7xtefRzT-{N0u#ME6Mh05!#`y?J)!!G?TA$)Ja c^nb^beu+-!Q@rx=%YTMnv-K^j*0VDJ0A%H-0ssI2 delta 12423 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 DXL?i+ diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 6aafec8e120..54727a60d3f 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -182,6 +182,30 @@ class HTML5PushRegistrationView(HomeAssistantView): return self.json_message('Push notification subscriber registered.') + def delete(self, request): + """Delete a registration.""" + subscription = request.json.get(ATTR_SUBSCRIPTION) + + found = None + + for key, registration in self.registrations.items(): + if registration.get(ATTR_SUBSCRIPTION) == subscription: + found = key + break + + if not found: + # If not found, unregistering was already done. Return 200 + return self.json_message('Registration not found.') + + reg = self.registrations.pop(found) + + if not _save_config(self.json_path, self.registrations): + self.registrations[found] = reg + return self.json_message('Error saving registration.', + HTTP_INTERNAL_SERVER_ERROR) + + return self.json_message('Push notification subscriber unregistered.') + class HTML5PushCallbackView(HomeAssistantView): """Accepts push registrations from a browser.""" diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py index 6201fb24ea0..d3d20d01289 100644 --- a/tests/components/notify/test_html5.py +++ b/tests/components/notify/test_html5.py @@ -8,6 +8,34 @@ from werkzeug.test import EnvironBuilder from homeassistant.components.http import request_class from homeassistant.components.notify import html5 +SUBSCRIPTION_1 = { + 'browser': 'chrome', + 'subscription': { + 'endpoint': 'https://google.com', + 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} + }, +} +SUBSCRIPTION_2 = { + 'browser': 'firefox', + 'subscription': { + 'endpoint': 'https://example.com', + 'keys': { + 'auth': 'bla', + 'p256dh': 'bla', + }, + }, +} +SUBSCRIPTION_3 = { + 'browser': 'chrome', + 'subscription': { + 'endpoint': 'https://example.com/not_exist', + 'keys': { + 'auth': 'bla', + 'p256dh': 'bla', + }, + }, +} + class TestHtml5Notify(object): """Tests for HTML5 notify platform.""" @@ -40,13 +68,7 @@ class TestHtml5Notify(object): hass = MagicMock() data = { - 'device': { - 'browser': 'chrome', - 'subscription': { - 'endpoint': 'https://google.com', - 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} - }, - } + 'device': SUBSCRIPTION_1 } with tempfile.NamedTemporaryFile() as fp: @@ -63,10 +85,7 @@ class TestHtml5Notify(object): 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'}} + assert mock_wp.mock_calls[0][1][0] == SUBSCRIPTION_1['subscription'] # Call to send payload = json.loads(mock_wp.mock_calls[1][1][0]) @@ -92,22 +111,13 @@ class TestHtml5Notify(object): assert view.json_path == fp.name assert view.registrations == {} - builder = EnvironBuilder(method='POST', data=json.dumps({ - 'browser': 'chrome', - 'subscription': {'endpoint': 'https://google.com', - 'keys': {'auth': 'auth', - 'p256dh': 'p256dh'}}, - })) + builder = EnvironBuilder(method='POST', + data=json.dumps(SUBSCRIPTION_1)) Request = request_class() resp = view.post(Request(builder.get_environ())) expected = { - 'unnamed device': { - 'browser': 'chrome', - 'subscription': {'endpoint': 'https://google.com', - 'keys': {'auth': 'auth', - 'p256dh': 'p256dh'}}, - }, + 'unnamed device': SUBSCRIPTION_1, } assert resp.status_code == 200, resp.response @@ -154,6 +164,116 @@ class TestHtml5Notify(object): resp = view.post(Request(builder.get_environ())) assert resp.status_code == 400, resp.response + def test_unregistering_device_view(self): + """Test that the HTML unregister view works.""" + hass = MagicMock() + + config = { + 'some device': SUBSCRIPTION_1, + 'other device': SUBSCRIPTION_2, + } + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + fp.write(json.dumps(config).encode('utf-8')) + fp.flush() + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + view = hass.mock_calls[1][1][0] + assert view.json_path == fp.name + assert view.registrations == config + + builder = EnvironBuilder(method='DELETE', data=json.dumps({ + 'subscription': SUBSCRIPTION_1['subscription'], + })) + Request = request_class() + resp = view.delete(Request(builder.get_environ())) + + config.pop('some device') + + assert resp.status_code == 200, resp.response + assert view.registrations == config + with open(fp.name) as fpp: + assert json.load(fpp) == config + + def test_unregistering_device_view_handles_unknown_subscription(self): + """Test that the HTML unregister view handles unknown subscriptions.""" + hass = MagicMock() + + config = { + 'some device': SUBSCRIPTION_1, + 'other device': SUBSCRIPTION_2, + } + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + fp.write(json.dumps(config).encode('utf-8')) + fp.flush() + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + view = hass.mock_calls[1][1][0] + assert view.json_path == fp.name + assert view.registrations == config + + builder = EnvironBuilder(method='DELETE', data=json.dumps({ + 'subscription': SUBSCRIPTION_3['subscription'] + })) + Request = request_class() + resp = view.delete(Request(builder.get_environ())) + + assert resp.status_code == 200, resp.response + assert view.registrations == config + with open(fp.name) as fpp: + assert json.load(fpp) == config + + def test_unregistering_device_view_handles_json_safe_error(self): + """Test that the HTML unregister view handles JSON write errors.""" + hass = MagicMock() + + config = { + 'some device': SUBSCRIPTION_1, + 'other device': SUBSCRIPTION_2, + } + + with tempfile.NamedTemporaryFile() as fp: + hass.config.path.return_value = fp.name + fp.write(json.dumps(config).encode('utf-8')) + fp.flush() + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + view = hass.mock_calls[1][1][0] + assert view.json_path == fp.name + assert view.registrations == config + + builder = EnvironBuilder(method='DELETE', data=json.dumps({ + 'subscription': SUBSCRIPTION_1['subscription'], + })) + Request = request_class() + + with patch('homeassistant.components.notify.html5._save_config', + return_value=False): + resp = view.delete(Request(builder.get_environ())) + + assert resp.status_code == 500, resp.response + assert view.registrations == config + with open(fp.name) as fpp: + assert json.load(fpp) == config + def test_callback_view_no_jwt(self): """Test that the notification callback view works without JWT.""" hass = MagicMock() @@ -185,13 +305,7 @@ class TestHtml5Notify(object): hass = MagicMock() data = { - 'device': { - 'browser': 'chrome', - 'subscription': { - 'endpoint': 'https://google.com', - 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} - }, - } + 'device': SUBSCRIPTION_1, } with tempfile.NamedTemporaryFile() as fp: @@ -211,11 +325,8 @@ class TestHtml5Notify(object): 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'}} + assert mock_wp.mock_calls[0][1][0] == \ + SUBSCRIPTION_1['subscription'] # Call to send push_payload = json.loads(mock_wp.mock_calls[1][1][0]) From 0d7d1253446790faf1330de790589e0e65e2f3ec Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen 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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 O=G05~q?k6aGXMZ$N-gXF delta 14478 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 a{onDVU!v0$uYCOSpW)YReaou#>@L^< diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 87421f91363..8a2e2e37bab 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 87421f913635d32d3d116d9e26146e965b1e5e81 +Subproject commit 8a2e2e37bab9db244a24aec570453653a0c2d4b2 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index c87976183df..eda2859f7af 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)})}function notificationEventCallback(e,t){firePushCallback({action:t.action,data:t.notification.data,tag:t.notification.tag,type:e},t.notification.data.jwt)}function firePushCallback(e,t){delete e.data.jwt,0===Object.keys(e.data).length&&e.data.constructor===Object&&delete e.data,fetch("/api/notify.html5/callback",{method:"POST",headers:new Headers({"Content-Type":"application/json",Authorization:"Bearer "+t}),body:JSON.stringify(e)})}var precacheConfig=[["/","92b0fdbfd90c14bca9bf90050422d5bb"],["/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-7901b14f238956024a19139d6c479d68.js","853f929882f981c30a7367d0bbe2ed39"],["/static/frontend-b33df7a012ea6d2aaf353c4466d6554a.html","018701ea26c562e9c13cb752f2705c16"],["/static/mdi-710b84acc99b32514f52291aba9cd8e8.html","149c8eaf6bb78a9b642c7bcedab86900"],["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|manifest.json)).)*$"],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)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t).then(function(e){firePushCallback({type:"received",tag:t.tag,data:t.data},t.data.jwt)})))}),self.addEventListener("notificationclick",function(e){var t;notificationEventCallback("clicked",e),e.notification.close(),e.notification.data&&e.notification.data.url&&(t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var a,n;for(a=0;aS!Qx-e0hFRc50DcRx!iUh@Zu`cZmKA7x4>M%7 zXyi^33vWIzwW)_jCS0#rql2BejM9<(Un;~>}}2N zs>8c$m#e*yuQ|$l{QuiioNs33|9JDzO7G{hD$eBv&+Rv<{wPZ=^Rd2gH*(1W7Umc4 z)7t%)U4B{pk$1_+((O41}~ZU#0C%w74VuJlmk?omKKaonvz= zuOGalbE-n;x|zklvrK39ge^bU{(Zik^*@;%P0MVzzWBGezAS%EcxkG@>5J(l*DOna z6h*F+m95Wyed=TUx&V*hKii|NOY7L~IT#oCotgW*J1Tbmzt5L{mp7iBlhqdX#c}tO zvk5mFw#;mnDlwcrZ?0wX@$!mQOM@hnHCwve6&)nFIgHmj&uW=ia<2AIfcf0WtUXUe zr@W0g_>?2(jQheVk#3eLEvl0;4kn+Q9MYP2#942~ivS1P0}>jGW-LDkXGo`z#~1#X5>cZ9KBR%3?tW zi@%bhCa zc`|8kwu`>yBcW|m1+TAE61@In@gt41sb@GBc21btHO1?yo3oQsSE9(oq=j9sCp45J zMV>ZkPHVS%Z5q+QWjU>sd9jIl$OVth2B#mlZ0NWwlNi+LVybnrDPQ;0*+&7-bK%VKA|KY7=};8c=R(3x){%xY6l9GZ|CWUQHVNN{dJvgy=JHIv7J z&jb^amh)t*^lcKjEXQ$o`o4gp8cSVL1g9IFzj$2YY`^4b&EtP2Xf@|(Tbwdn5Tow2 zWX1`lgE8K%EJt0ZJ!vUvG7npP@$HV4uDP#19)Fkqr8sug0g2v4At#D-Tm{`cCuQ|0 zpMTt8cy8ySCY6W%E_*f8iZ@T2+7;2Qb9oBq1j$|}Uk(GUloJweI=?2a*}kCbYLc!G zGq2(zP0vidna6H;=e}HaU8cO7N&5cB_Y)$|2Kc#rp3@?sa_oY_Jf_2JZicZ2cQt$;FD_#G!~T8p ziDwOuG_zP=i*aZf-fZzHS~K6aql# zH*;l+s88hIzFm!E%?E`9L*<=>vf%A1pf z=SNBX`Sg+Z)72&N))VGU$gSM)BrR^?mj$kBEafhHA70oSZ#Prw{PV_@_N7yvSC#L} zVYnSR?albN(PQBjxrr~ICCX~QV%0sT zf6R5sp2we`|C+rrxji6u%8H*G`F$Id-HU7gpUR1|J$#N;mv2S-lRK~7ZZ6)n@2cz8 zz^nF)Gx>qV4={h|6WGv*!j%@;Jk?0S$|{c20b ze~#l%BLgite7-+_uw?UN{zKR5^ryuOPPCJJ!}gzJ&NrFj&cs{CH}`*ecBbUY!IS?R ze@{FtS1*$LPh`rsH`|%h>z5tO|Hl!qNk@nMp}xMDeZwkixwns7!Yu0lf8Bg}>$YY6 z@fYMLUQ!l|mnX84B+MSmlnwgj;oO0iNNz20z3tsO|KbODm_oJD&h5zc#Q_0Wu*2ur^ zKDm4KuAh9oL4V&ig|}|o^k$|&_tD?4;|ttwG%ra$ncF>)Kk7{0X^U4A^WO;WXcSxN zU8{TM&-v$>=Z*NEo?r0T@r?e>z4c4tZ_He+m)mPH_4l99y;`AP-#<@F*x2BhAI!}h z`}pSf<<}%{Tr1c3c08`< z&i&R3|Io+p{&I$G+&jmjWeV5;EY-=d3d2i-6t(5!S!J__K%H3u**%tD(*PlP| zTOMORS8ronQgw85ajR=gyk-C0q|)H-cwd9?4N50k{^uHd`TjWB*qHHR>=`aXk03C^;-S=*oGyZfm``&xeqeX5cFykCxmFUT z+jOUXO-l>bjyC(cg8BCy8?h|TU%t_$b}aLwHq728=lDf1&)UA@jZjwo_k$O?wKvxN zIJj)>yQbZr=U*!@u3{An|FCthZfUZ2u-3zWKc7lv{f-EkD)MSE|3Y57nVVY0XXovV z|Eu!ry8SnH0ak~$mUmhNln^CrC_jV6wRTe>(+zZ_G=I5N!PyITk-GJR&hPYjEvph?eFZ{s{c>^zGJ0sl4WJ@xvJ^& zBG#{7yZADHY;g6%erb_Q)BeA`uD5r-!}M=_9o+`HUg3@D71vAcI1(uAtk|$bjWNXdv>grh`!c}78AK|m~ z!L1ilMB8e8CyR=ydAfDYNR@fIByyUHR^p^%Hjb+!8B^A`r&dOtuvzF7*m;04+|6^E zg?P8kf35CwF?WDw<4Qb)oax&U=|BJbVm$j4tXNd($PEy2L|B zZ)Tc}+0g|D8ADdB%!-=vWKMvm@Zm>I%Ow*#7sw=Dn(1U}rM-w>_LT0W8wJO@nP&xv>DG7C!{zxAXkfKBPLPeR$!jb4*~p} zB16WSlzB#nizaE!lJ$&#Su`nFsoO>4sO7I2i+*Y*&*3`5zm!{}tSR%5;etacLCMn6}sEJ<1G7-*Fy;~jV`qc+c=uW5P2 zAtw%B)sv6%JFBAfrj==HPhUCFHBn>o0$U*Webc+wnkxB4IGToT=?H!^ zxAlOJLvV$U!eS>GuicC*XI;NOv-BxaM@OQHF%!e9_-wdr7QogPh5#;NHbmHeu|O3X+PJ#Iet}|E=|ELgv*^N&EKyJt$qx*T%gf zbn(Npr`7w*8$ae2JUqL%eO`wG$JL2DQ@=CSR_;C$5Y}PzqWZ^_W97|UImag@7{>!4?f+rdI`)xMucJJR%?AXry%DPDO%i=eYvGTJv-CHU3 z?&6l}pPNPQZaSWzG5I@t>7!N)o$~dwV~a{{rOpT3{#a3()X;qH+}y^62e|igz1E+| z{ab1Eti%h4|ICnIz9C-zc1z@+j&~R8!{sI9SFPTyFyrf|4ex&K{Ik+~m6YLEuQ|zu zGG7llpH|ohs<-$pzP@zDF7Nfu zztt`D^iSP#PWUx{^4xQc_8igQH^%IDb!kf}kZ(zUQ1W|5HqT|ldCp79tCwx&JNJ+O z&iR~gN18Lb*E_!aR>xkzS1ncZyq{s|s!N3eajrXmv4#Bo_Ci8^%c0-D_1Ev+w{@%Y zpGAq?TUZ6PpXQ{0+F#SGSJT_sG;{9#{zDVoYMIwQj}Y_lI_zUs-D17_mf)E`E!%32 z%RaPBY&J1Rhhl{CK&bR>Fwf{ zbE0k)5oh^(d`>@mcD>n|Tb^_EmZ{2DgFpEB`~8~C&tEKfD*M8{Zw*K0cIKQ9xN}st zr^b?-b6;3*`*Zb(qwfkHUAg-CxpmzCUSpOykKLCWuFA6d;6IK1id;m=!<&bGKG>|t z&TsW}+siMVUzN9Q*R?Q@IC8f4`vuJ~`>icsd5T%Jo6a1$U$*#)PfQHUjrOdRl*XPn zB1tP3d7U@Ox}2CUadr2*2=~9U 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),c=1;c6Z}vRvbS?e5)bGu=T&p&_ygT_v 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%0Dl) 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 C8E8uY delta 12898 zcmezOi}BwtMt1pb4vxdxyEd}-c-Nn*d*Lb0ahEwF_{-W^_P^5{we*Tz?wMcR{?ws6 zblIkk`zsk=G?_D|tT8A({9xV^v!lFRpSXAeuUxl@Ses_NNL}pi)#+9nZ*SL>{I#QS zzi2Wa&(|kff|BoYFTQa0W#6sc!>GJCdzD|9q+RYx$IGnj3p^jpiDJv1BCHz^ z);I6DkvLao!n%XpCsK|D@Bi#B#J&D()Dq<_<_W^Gs!1Z2&AaY*Zd*L<=)BzN*QE#6`ghiyVi^^eQD+)H$VUovdo!RmBv`FqE+ zZ99H(NV8XnZT@mcYO#cT15e=fWZCR(Nvq}*I(T2&9(upcIDQR_?X#{$uU{m@FTL~D zVJ~0h)GYDsr=B&N>2xhPd+QY2<-E;PIS%d@WuEi8A-|>K!F<1oYcDdET(p9_!4@Y0&@ugy6}9XUvffY15}V$R3{_{?lkz*}L1ODM5FNG-e0xJ9y=z z{i;i*5mzfV75z*q3!U<0y7IRroAf5?U%fU_E#_s@zjn*eR=wj^a`nrt3+7DSBD}^) z^t#9_+w+AdS-qYAUs<`&;DGK}%DIw_O}kQ#+1>fHt75h8#&dE% zwZD5$a+xT4m5*<|FJo@d?4rH$GWBXdh3r;d2)QsZZG)rpv7@Tl?GbCV`goU~HE~u| z)-mn^s<7}&k8UgQ8*G^# zxo5pz=|<^BrRq6~rFJX)S(m-Myyv2bQtYMGD_Zx5ihXYKoo;a1YA5TpiSDyMPv7M@ z=NYSWlalY|nyjO991ce46*Hg>-Y0Iw#*WJ%+jCTE|IM3AkX~>yf zx|6@@t_e!=o4WLVgWH;}i!9H2v)=s;wb`4Vzi-{UvjHF1o_PFH$SzSzKlhUF4xRif zS{54pb|0!YEYY*y`k`g&K0*J8tv%{B+nMI+#hUeQedjzW^QP0Ju;AI#J9f`8cv7V< z`8lo7?Ox%Vn~n94E6%Fzd@QbIlsB&}__V*J|M_D^ubAr|s#X_^HqAN6ox1v9`Kg>` z@wc*aXK>f7&Hugl(CYY4>_^?h19djcyQT6nR;j3BcI#&)O&jgIEJ5|GCu~x4H4C?E zUr$)vX8E?`NyEPV{XvWY8j;KTeWy9eUEx(KdC2)bKx!(hr}eGK`pa^4ev4_XP!Yr7uAY&ljlt?0$v{>bdUmnkKVB8t(T zQF|0J`8jr#c9s9Ao0gna+qXP8Baqp;9ToP$pQL?d}rOnamURv~KC2*qCv6 z!#mz3Q=VQs`*>dewab#b=law?zA03iFe^Jt`6pM)@&y;y#jnp#cAK{OU8Umu(AzuW z|F&9r{cPoZlX2-pSjo+$VG~!fJerp#vf}jYrrx6UImwYpA?u$e^zlyX;c`<8Xlvcv za`gGHX&n1Y&ILJrJauuZw31cUZg(aPXGX7lQ7)7G6aQAWJ+u#$I;Znbcxn24mHPjk zJpV7w+@ds{@nq<-`&Ke5ra5?hmng1ZEUPe=yJ#bmE&oO74VyT3sjvLixNP~nIPN2- z<@ZRj?T|R3y2Qfo!i4QNFNSoy(q6tnbLzn~{@C(q<*O#HTJ3%MTY¨MBDaE;p<( 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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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 delta 93937 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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 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 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 Tr$>|i|7VsK)IMT*goyzFExrh6 delta 35955 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 d-mvyfAbqUX-J623ozHnGxKL0aIv(n#x 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 H5e5bTamzIL delta 2174 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 K-eoMpzyJWJ3q&IT 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;c_;pxFS~{Z@<$Ps+qg1 zT+`U9@2!cSjP+OL%rATPVQW6P z#~@<%nWGy0!ViCzzpXqL9XapV;yrh-zmMKI{dc+M`RAH{;^On`)u-1NXb80ZeA}Zg zTxI@ja)#a6+lC^NPo6*fsdPeonc};rJ+qfpR2<)bW|GPIrrk%Ip30@~S$yxu(esOT zO}J|Bn(5uLNBHdL*O#9#i|e#5f30%*_o}D%JId4du{Ay1u8>;zO>fq*#~S@dLpNM& zeO~*K^FB+q?Xk-yp7%fKbg!$ZzmTW@XVLvD#s>1A&WWD??mFlA#V;!TMeib6lf@l& zd-6uz`ziDMdj7Kj(X5ntj{904`5h}>pX+=(E!#GJf0)DJ-Rr8-%deyz+TQ3N=6Wkq z_tKkX&sgQ|=^b@`@@?iP>AK>Rmvb{>zpHg!nrZwk?Tf^oIZrhE^HictxEcyx$HmvX z-;`5o7s%*O{gQ6=_GJ^ty#$Q}{wd#82-(552UH4v|{>tyXuhFw$rS>W58`2_q z?9&6K?xyH)y0&-QoXh|H@kq3HEpM%S_W8pSug)yH*ulS#`BUT%$3EHW&hv{3tbG^X z_M3AtUjHk5X2HC;4Lq~vEIE00_2k8efB$~JW@>%oVecC?oJne)uM&^jy!rMs?8?ld zLROQb=4M|CjP$LZi`T_(Q?vRgasBY2?QQniQu}0z8Tl{de(HSB{XRyyap{EztyixJ zESw~8SGUCXUguGc&bTML1La!NSmqqu)cncQCa?6cfzS2pdquQ<dS8*U;d_Vg3J@2MG`ws^PXQnx$wfWxQ5%W z)~%fHS9iA6{9Vkkq&J;EOHO4p*!>Qvd>VW|q_o=V@A(F9*+_xI^_PtnWQMg^Yky^K zWZV2gSpCW4etW|ili!wCSLsyouo!O3cC3ze{phLNmFYhJ)12-40{b4l^k>+)yL>}= z6nEOiJ*=-oMX$}SD$vU6TloX_5rt{uXgwq*Rgd`fr! zjeGVha?MT&IiB6enkSLI!z-|U9g|;VN%3wc^P)}ioc~X*;{C7rVSU&O*U1N!*$XyT zU9QjKs4jB$`x!dtsg3PP;fCYQcAIOe#ooIt&X#*}=wAEx?%02S_T-A^9OjxLeUf!G zS6z1Y&qs?go_&&@o%!_pcg-T%`+09qXa(p*UUqc;-4n0VWo8$h%kgjL*6t$Ly!zfh zTV_nYWY+3^MSZ3s-@-zHgy#{J){2cK@jebo9uBh{78Wo5TWiw2KR>@?-_@D3l)Pme z>XerX{P}l#cJuT~JL_li&kd&h+cWu$h0#)$qbdSg4l)7v<344a310vA_OsJ(&t{k~ z?c90xk(1G}OPw>+E?R5}QNH!$cV$)e@xx^%^|O5+3vz1Q|Ig^cvMa#C{p9l*>Ba(4 zJKiNv>5vK7**Podw)}!K%}H!M$$gi^rrJJ@FS0L~FRr{O*+GThJ3c`}LF(-0^u6=z zVoXv>~XSDWg;h*a~Q4W*=oPb?Z@X2Z@wIT zW`9d)>w)@~%#0OQU8^ga9?k1dUgY05WmoK^eWzXtcIAG^|08NyADFwHp*~zkIIleA zx0vw{9jkWt<-hg6m2dO^-p|)=eZ2bi^6K3O1gC5}p8I3pwe{r_pL}$AsK{M5m$hDJ zHw)uVTVFT%2@*xB8tY2~^YY>u&+mM6xR5Dn_wUfhj7y*0sehmC$MAa@L&%c(Nebur zI{w5-+w(MDS<}a#Q!90YU1#gJ&{=2FuXv`$sI^T20^nJ2^+o|7K(8tAI~@6F%l{mA+`q zWqUTa=E&vD8fN2tl3(5HqZM>|=asS-&NzAfq|6NS$Fr5~KO`kt`P{i*E!iXb^2fE= z#t9~dduFwFrg#}7C3zpvc&3vSDSy9Bu`@Ao{q3nS*(v&qD`&(XUm@-K@~X_zKRjFJ zT1kY4&N#C*BG{rVu1%cfkl>earppZ{j21`rSS{A|3=`x+k$^Q~jf+UM`mU z0`YqqI~nIO9T4}F~i5x;lInKWu)GIiXEAKrU7`0neuGt;IU{(E#nSxDG=SH|s0E;`)t?BDGZbTS@oj6C$ZN-a9eL}HoG z{zC`r*|zstzAB&Ikv8#x>9wWLuN~W15*HUbd$yF*|5rl4elNQCcxmsyXJ)fv)#r1| z#f$vjn(_YZrEmWtXC4Yxm^a=1eY^Va-PPx}_urKL_VC=D^3th%+wZ^q&-7a%D{j#i z_Ggu`z1wfMSF@|P`KUDA>9Wy}bnxuDBY*u&_la)9`WUPFXIr?=ipLnTS6eT4R=D%` z^8K50-<@n#Kc~8IZIGblvSf>`XYOSy1Ygf{`nh@jkN#<`TTK2LikK(Ae{%BQ$%~ww z9(`M{96Ive+i>Dl6Mvh@W}l{Sm^SH4*mw6s+c!<%onqOu*DLUwv+-RahMYGnP0Adg@?cX@kiEeyq{uBJ|Ams#Hj z$ zd{q#C-_yK@+7oxJW&30M=6Rt}-t1J4x9d*&9dWxM=krMOje~RZ+6{XTI-b)li@Lby zs2!74?%fTY4Id7y`gQZw*>|$?^0JQ?1JWU^5@6oYB_uFE0=lw5a@s9 zrR-F8Os1wI^utCgrM%CFtnwvg7u{H6+*+@7T4&mIZ?(mhvzR*H2u{@~D16JdzxhYr zex7@a=YLe_Ja*ve+(!r3YkL1&amQ=I@zV9@(>fLu3LO8|u}ybL{q>T|{U7pP>YJ(Z=G$c5y>Guv?&X!2@;NWu zEg#8Mpk2Rx`qI>r)kV|ZM!diC{@eF^n|J#g>UUcHu3Y?+)7N2<@Y4<7xg z8#HZezU9NchcCXf*iw+P`>Fl0=PU)=?6)0xbN<{OZ%6&>yHe_BPm6P##*oq`dnDt; z`}eBPx4LW%ZeO_L>yHJzHjKGt2PBz(<=(97Vm-kk>9p^7*8F5cKRfBGd>Z=u-Ts~~ zpZ2m{q+vt+o?dG)vp;qo^XEwUOGm#+`FvW(-}cMgbITNXnHT~LeG;2nj$QtIk2S|| zx=VuC{fSJ*&6d{PiGIs#>Rn?6Do zxs_1(ABO2I4>C8*j+UE$C%yQiB%@7_-O+H9&+gNM5?L6{C)y`2>AR}MzThiMkhlr! z>({?zr5w-nJUgS?HF?SM9p9wAqPR4Uxba%(O_FEey`96b){4!ggJtcv*{rvux5i#+ z2=^}2o6@Xhqz!LisJ<51~!JR3s2EB8HR`o1O=A*`mM|RdMJJWky8z+wUhN_=B~1e(4DtfrT%QjF0q`Q&w?|ZcSdtR@5)*J zCZ#lYviz&92b|_JFRAHBj}qN0y0}jB1cS$JlP#0)^Ov`&TkC%>JJ0v6EYV(GK!MSB zZ|YM$>CRK3?bf&3t*hCu9FxzxyPa2C<6K-q4#x`yi`;|SHy#_a{7NY~d;GH|$G82K zn_hdH{^9vj$J10lak7oe_J#H4T}FCK*FEeI`@TbV!bkO29RDgk;@KP${H_T4?uC7uomzC`?rSTwl_1N8zN!o(->s z^L5sI(Y~O3=J~_`k)4w{7(-$ey#j3ZNi0-nUG{C=kt-HfOS0}geT)NC6ct~ z3e(r6xBlgqTv&Z}u|V55p2cbxFF3bs+2^Ny=F|Su-~Ub8wzFr`mR4SVZ>FZ>+f}|h ze7?q0QpVTk_pR*WhA`uZO#vtF>8$6wXe4+-c|+NkFhyOjPU)L^^VsTCPCjaJVr{x! zzb;<=`n>B|SEenBy0}p}_P6TOTZ=BfUcy|HXLtBOuHCoNBkcvw4ZgJ{vB!42`*o>I zA;n?S&v^&FtK@8#Jyv(X`u#TkZ{^$lzw_5i=FOkGPiCIn-h0+5VPA}u1Ty6t(qxP3O2* zBwidZqgB%vmcC_o01vCwY+;_62R^d|F?^eP@ZZglza_;Q?l~Y$+w9JWkH~YwL=AY$tuEkLjZ&amu|9hC3 z%}8ac%n!RRICs{Ing`o6!dBgy8PTXpSt zjSx5Aq-#CPSNzyqviNVe)`@ooGe0%t{QA*WXt@7jW{G9!!9#C3I~*qFdKC!uWKT{M z5UzJn%>5fMN6gUl+~;n!9l|_b*Di=1eOutapU3vVeiqK#St+}2E(yB3?AZMn;a`bN zyS&zZ71--)s#sw)FP$+$@qbge{JZqm`ulHjb*|02(8MbF<`m!GpU<~fNbTPoW34|a zb=}-K<`q(jFEY;-X!ujr#Cx;>&lhYSOnIzwt_E zzP|0o!`f}n$~iafdG7AMUjAFGs`u*mvh(ELzn{D2K}zFE*49slPu-jP%+KqcsA;Tr zMVQp=HKl9M{Pa5au_SNj&YwZahZ|iOEkol}TKQe~-VbK3oV#J=?`PLPNx!u^`P}S? z$w=bCTD6`%>Bl#K=N7T0+(VH`;9B!++%%~$9wQ+e?mTK=7 zwLqJrmTAg2ZckciRn+n5p!7w_#y#_jcN6j=#{lh ze#%-FH2}|A9oiB|lUdUg0cD9B7{PVibj)E#*RW`I=)XNMIuDwKi%qG zyYBhj#fNRfSFF}vdd6=XO88tnB4Hre8T* z>yOB;PK#$h%3XhHsr~2E{DpN!k84V5W4_!g-?ex111^@;KHeADelBeJURHguW!}N$ zuELWSO!cfbBwb(;)=PcHR(;87=YlHV<(bnGVy_85o^V-TGDkRU=I(_afii`D&Jy80 z|5eod(&bgV>NYK%Z)|<;*q$Q^vn{F{H6)ivFZ?U_nCUZ<@5fE+>uUpJnG$)JH5IFs zeIjM~`o8;}<8yep(k~)r=6bKi9vgf#if7gy%GoLOQLj;T+vGcUT#{sD&Ko{v-e)Lw zGC|s0+vU9(|LtN$UDn6nW|{eUEWYIMkMosRjPGP`hc$nKqm>?CKFRQ(^PO1E^!9Tz zO=o=G>a_iEz)~+O-ni*W$rI{d*GMG3`svsk>w0M8KE3~Ci)Mdx`1j?U{(|`nZk=x^ z=X?IihI5!-SH6C5_gEz_N&cv$)zO(tcMW3b2J-nauq^8s&`^>iN&T0k6is#>2rqrL4 zv0Ul*>0H5y&E}j{&TN$h>6d1){7eeW&waEe_KM*%wMw!3uO+*8d}q09ttoeH=Hbi! zFD7{I-P!+AaF2YAS<~_}>B1FNuQq4@xcvHOPFMYIyV(ct@Bf{{(VBK3WNnG|!@Gv; zxu%}YC#p_o%w_5PoAv)0TMCCseeav=h2Lh~uiw}E>GgwM$#sXLGhKO>$^M=E^yKQv z36~Dqf7qSD7e7^uw!@Hhyp7r~?M_a<;QaQs8z5BIm zTGjHCSO4x^KJSoq1&>ZwoI&QX(zv5ZlXm3Wxvwm^f5Gj+9;SIoIw!cr4;huNY;MYq zyVq5yEu#COKsn}Fsb|&(`yU6BITRto#Xmpe`I^E`EMV`-DR&AyH8&A z>3Br)mdT6{CBB%c9?FY9(6+=(X`yjp!;4xyy1jFsB{6WHq)U7LK#nkVydH!Fv_ zjBLb?h(i%eEfzkNI5=Pa>7$yi?#*(>E528hmrX$MYku*} zcMVx4p7p1d78D9xIKFSq(a^OKT)RGoixi7~m~s61A3ipzE#2pH)t;YGbW`)5%JOX1 zqD@bk^zL7o>JYvv!(Q=herA15%ExC>i`U4;1Q=Tp2sb0pXH?z%1Ao7*roalD~SF>Wx3U zyfO2C&Jq6N*^f;w$%hy+__lfbxCsWWe^tDFO3vy@f!)b5Mcd;I=9+KNEX`Y_-!L!c z<2>I8Tg{cCMh_<(*wK||e^2PI#EzgUx%if!m3t2AZ>gDJ6}f5EN$)3yC6YII?VYBu zJ(B5fFVa`ad5~>wKh2VzujbvP<*hy$E`RHJ{nqXM)^^|qi>|J$TYIe>*WPPC!^#^3 zau?JdIkhTvX7`&nk!QU2J}OOpvXAqE>$2^ld0ad@v|~=?G5*sL$;;C@-BRo;TXNSV zZ0h?vo-R)tQWQ%Rnq-cpot3+P;_re6?iQV&hHgpc?k)*+ZT=wb_0A&e`5CPOZSI;< zE}pea_3E1rYz$6_d6iUK`_^lkb-}6HO*QgzRrc3DecrgE;PSQ*ubLvSIaj9aDD{e& zdaSs<{*gmr@a03Dmz#WIo7VUpFiY0IRQq}f%gMz>Wfd2KH<$3mcb78FiC%Zb!o&IP z^weY-+VZfeZ}qZ-C#_kVyPK^gXy3v5S87( zCr|j_D!#)b@+?F^r>izb@%isZkN(-&?`L7T#I*KXrkM8j%|SaRtV+#4s98CA^1MY8 z+|O7_XSeQQ_4T=AzTvO%KS8;@|#y3t#z&-wzhgUbd}9%GGcEoD$Kh#r*}$3|IT-iM-bHKO#SE z;;F7P438$}dgMl$8y)Fa+#dC0su({vL&kK6ja&KHY{DPr$;f+|W_qW-<34ppcwW54 zO-U`D2b&Kwtf}EyK7;*n$gI2fDxQn)o85bGjhuSA{DSyt=l>e*thpv{f2F?0=8`;r zw%xTGW*aolwLcP@k~QIawo7$@kK{I=zjrFDp4#j+SIW^l>S8mw<@g_+%+O~hN^Qw;U!}}^RUgUwW^FHAw||wK zZ)VR`zMWsccw~sp(iNM#PE_Gz|L2TZ2a8tMJ$d$cmfmwq&xv)#!4mv+OIc>UHQSxN zIPe1hzn3{>`@=R}*(o#aF`K)P7uV9hhc|gOH)khBf2jBIjQ#UqchKGS{VPt-ZBgP~ zaB!8IX2Y#N>Uld~_ ze%{w>)pz&*|L|SD`hUfz$A9_#=Y5%HQ~B%h{p!~{XSW=g@FB`yE<@K_a#nDOyxJY1 zM7`XrnbW+=zOJ5U^}T+D^^52#rJ(KC1a^P_WU)0On7#PF`Jay`&)fg|bNT-KKYzaD zYs|ONp7*=%-`=k?9UmSF>^VMF{MiLPHs)-DTBb2`~~^zyn*bq;x_@^Oh* z*{gW9-oBl=B~Kpm@7>>Mbo1bs5{@TkegF1lD>jD<9X>Iq&Vc`T(}CM!T6vo-?w>k4 zCCG8czR%{54*kokkNd6V-@kZ+c`)0lzd7e4Y%eaJtSPHlzf0BM$65CB6+V%>j@3PP zY_k`YA5n|c&}4G=^nS85&G4q__Wh)iSr9bJDM(o?T5p8zY-IO?0=FnCqHUp0sSTJe}%)tmfQl&j}Nz zE9RB%Kfi0A)rz!(PRFlA?LBZpzgVz-&gZ|eR-D&#Ju5A7A!R$C+!e-8F{&~leOy>4mrp`>cV{=VB?54&= z&K{vHJgl7m4{QwE(io)m`q1f%>$3!w)|+gps!%9StZFfRvW$Cb^9#D`BiO7hc!$H% zLOpxRW7#4Pol*|%+5a*!E4mIh zxXj$x(Ny=3tIa7(T26ZE1koo!^DFiru}WE6w9fSQk%#MoZTeq6I=QJeL@aJk8+U$f zZSGltur*Iz65{i`nDmyeI;3>D;Z95Hq^Dxu67ernMH+>g z{EmxM^cr_{Cn~)chscx6XM+ zH2X`H-I{rMqV##CW|o=W+s$nMy7lwDUV5SPV?*`QExBe68C?m5FX|T_&Te4*$=LMb zPy}~Ola2K{hW5^R*};*A!?1ok$=+l9?v-W zmtpJV*9S`%$UeV*%k0p#hOKiZdVl>Dd874PnqKpUN(uhwYBFuXnfqELeL9!ss{~AX zv?^WOvtVP&js|X~a~scd+z))56B6;ng=t32&Dge|91-6XCI?zRS@iq2DZkmH-roAP zM|{HBUQZBi7j$HkQJXgD@UN=2m-EGDyuB@T+i0cW%STnUwNn!_9D^#WQ;&AdIr&6D z{z0h8oPF}qbFz|^tI`UpS0?TGd_m;m@6&(xPE!2LP#@FDD0Oh+c`d7xOCx3O-*D36 z)HF8de{qf^O_YWA2>!DZVFBiub-5}@@4-ypk(*BQMgE|m>IR7b zo3k0$xf1rS`FdmN^XaUYXFuI^I{64oQm^(|tFSlT>{ql5QTxT~BvQx-|M$N1`KZIzy+ zb4kFMyGQ6iS=`5kQSRKpd&=SF1|H?yR8ss}u2 z*>hoD&3a`W13z2FquQs6^=x_$`##C*&pdtXbKuX4=Hz8tgW{$wos)F?mH_ve8^0QrH`Ec&-^qKqW-CC~s2%k4I)Xe_#&+hi42G?0dS&56Ev!B>}@f5>t`87`h-rYR0 zmf_RZ4v~6quNPm}?zsC-`DV?`&cpk7f?hUD7hk$Aws6UzhhFnwXds7iF|% zPeA{I15Zrz*R9~az)veZ=(xi#I*q7eZ$hhV^`*z0t4Qr%czxMy9R?k>1c3R_{*t4g5 z4fx**Wjf|4%)P7|xQGlbrY|^8%OouNEhyRUdW7D2^fwwM7YR!U$o$ud2|Nr&K z@-05I+GcDrR($#Yx^TktriVfYa*FC-EjP3DjGme;Ot0}A2*@Y*YmzC_&YmBnq zz30HC$}Y>v3zZEQeBaUjf!juHrbl0NgpgI_q-VX`rhJyyo6%5ju=VZF$=$w;|8=^K zn7%ylH07k_{s3;pnoS(5%AT7JG1EuD!7Lxh1}RM}LJh z?9JQZf4Y*lB!BIhA6sNT+~^1>>Guwm{QH|#)9%QJ`p-?d9mg)VNbEZ0*Jz^4@7a*V zdx$lA*Nu#SJ5|qV2l);f;@3mlca1Qjwfm_U(l9_F2}7 zHM)Pga`r!d7VYGHuz|hr{I!oCW{T{2@o@6Fv?(X2u^*qiKW%Nf_}Ut~*+r6H!_Kw* z{-2?|U|$p8hBwC));)Ww@Ofs;*TV@h=ZaQ)?L4k&v+7Ie#;ykkw)cfwtjw7lsU};W zUhL&r^met%ypN9hC$|4c*eqUh_sQB@GwP#`XiZYu^83RPk%L_e<|{bgpL0z9ipbZE zt}!fiz2(1j>NR{MCvRuXPu=%$tF-2<$GexwaJd;cNbZ+^C^fw#p!jvy=AA2!gjBxV zHe-9G?}T^J>K@;hzK!#<49Zyv$GGh&Ytxt@N53tTl;rx)ihqGXLChPdEvaxHd3_? zk{Z5~YHDRCi=Mi_G^AZD^KvK06${JOM5|7|?xgaLsSI0KdGh&p~|ye~VdR{Di-6ld^EJoNL1`m}&^ z|Jaj_r#p$s2z*O?>tDddQf#@$<^zk|9Wl8DtnMF~madpF*ZE-gv6A|yKTe2S$_W+R zuRU}6=6{a=8}G26Wny}Gdb>(fe@XqWsdHB+i|FhN$m6;3{Ny7Bh1a_pe|~*))A-@~ zcX#8{NV}AX?puKC? z{``JQdW!MT2ZOzH&g`A}>zb?aDtV2ziFG_Hn2#-UI)1h?MZ00n{PX(1GEN12 zo?b6r(&P9<3FiwsaiW)p(pSTj}Ae$tPPK z1PvxKoR(?esD7PvV5NQSH>cCxGu9}oaV_&zzWKt^aV~eB-}c!ps?WuL9a$<@yXGSQ zi0@c?F8XW}B{@{T5NaeXDTkTA|HL!za(x zl#oBEv^F-rCCT--+~UxbyvN*K`8zJ~D(~L^e(lYt)0R|CzM`q8pJ^n!UcJ#_WvYAM!hNkmjVI2ttP zOse0S9$zV;q-~$h8Y~a^DqsKN@0Twx@7GtI`gGy<@yqpp{(R=QxBFXZ``z3|<3q~b zJ%=`YniKc$#d`b7Ur(0H&;M4}5G8%%g8h~I_x#s$ z`{emWw?ZMc!s0wDG1lT^ZGW~fOx(Nv>7`j2j3UttOQTGW^(ritO<2ct!ExJ%NS@ye z4o3GqcvLn{zH)hmk;Kb)_u9j3?H$}gPQ8Cwb;!kH$~o4R4i?7*19EKxbQvyui7cdt=`}Yo3sKKmAm%_g+2TI$8hdg%*XG%F*%Rf7!PD zc&X0SbAFPexrZ6+nlC?>8CLhq^S!Xcma9;@S#&(v#vUxEZN`zNv-}^9W?OKui`Oy;j&XbOX z8?Fnn`e4@WR#;!htz9+$bc@Rev;Idb1@Go8P2gH}{mMx`gDppdK3&%Qc{;Q?PCP4M z3E!1GrtQ}^w0wy^%+wXQWEWGLkfxyh(RdDt6Pgp3nyY?sS@eHST~t-@6P4LI>+ZVl zeOVr{c?Z|-4P1YV=6NPfKf!Ha!RoBq^7xRF*~c?EFOyckUSBlzb$wWQf%Dqax=Xu- zj`xcA9&Piwp<(`F-wlnlQ$KEH{gSbi&4^o*dSk;4)1;K9+Do?<=9v}+UY)gIpE;Mm z%KT*IVB-#+i{uV#!N!o0FK|kX)_nLVI>kgbe@=_+C zW!=+vGqc%v=dQlXIyLfUhS||8Q|cImY|1B>W=+>yKOxBR!6fU1g}MPxzITyS@sza_u;t#&WcliyqVlSqGd~i`FL>;9dztyT zihF_~=hZh2Q5JDr6#dviQ-=ozZw^5mBd=W++d?GB26{U55kny8CM z?5|Mr-&1wyQN41bh$vs-{xciu^JV(3Uq9}(<^H?{|HPQ3&p146IXV01#WaiNiwEqL zT|TsIi+*;c>KtR3-_=ErYNEdA?A*^@<8kPC}KMcyD~jKZhC2} z<231o?Z%J(zvY^+SMzt+=EAztjSk)iH@k50r&_q_+}hK|=pe~Ze?W7wyG4?*mQ%~7 zP7|j8I$M{g&K5MzR_VzxlTB+2Y*$V$n>|A}Vb3iwfxtW0TY9~J*1XQ;_PM98^JdR- zuUHX{M=lDb%Jjv80)4OpV{WBvo~H=hLeM4WvgAnMkh?y9w7!-Op#tqw_5AKAB< zYf-^{-cM)c0+oE$X{0}jeOABU!gZa`&a%eb$A{}r6&9v6FO$(QpK7xIG|%1XWv@1D zI$5nCD3$Q*oMM&E2@bp7%}?D5)CJctz8Ce%U+=;pu(0V|z^2WtJ95K!r)W7a?V6e+ zzuR@%`k)(<`}zYftK9GuHr=_I>)gHh-dfy&bFS~7|Hqfjowwn`v(VcUwi=5Y)(2hs z)9$v&q-So!8aH>XUmt2qCEVuk-~QC>)Z7S#i*74Ixk9}3TNAZ~*`I~-o;p;}cwf8hj&MyAA-Lkds?d!6F%0F6%*54`RlC|k*;_qlOzw>ckT|_HqZ+L=} z7e?jV9E2W2g6AQXzloBQ8U*zj%ZdwiVVt(3-jyy$mzaZAddwJF7~zRkiDU;ar? zd|hqmPEBss^m2oB3l!(pH;XWd>1^&^QNv{9;3Mr`62<7Vwc%KW!*;v#*Ss=a=5Fgd zzHqNzdH&4bb9djIcBjW}z75a5twwPkoLeqbUFH6Ha8JRi6LSx(ToV7X|Jv!_)jfVq z;@hu$?X0m_*e?CE;k&Ap<@`4`D_M;Td3JUF{-DJxd^?hl z`Y4LceV{#cjdL-hfbnmQ3!e-EH$KdMq4}^h@L-Iz1bg-`nHmB9Yxk6Iinyo!Ww;k{ ze$5I0=8X+!_DwEYm&wfgJgk9h`=Y?rXX@WtmhYIY*{jj4>acBU)2Cv)Y}d8Pd#3Cv zt-Sqe+sTQg_4iYkp0VHie)op$H`u1mJM%><_EG7Kp8UXd%03~{EFYJ+{&TJDZu@sA z-RfHVvGk{tm(Ev~^SABKfA;Tt(&p#+UzYs88ZzNq{o!Yix5%GX2>5-=KTkbdU-9MC zZk5n!KJ{N&7M_`wwfymhpgT-jOxDbKvIU+S*_ZxZ!gQxP-F_?o)@aFD=M7hK|4Dx5 zykWaaT#GID@e?>X-9&eoHaVB^^!01r`0@#!&`i>+^N6in{+;FUqR!}ECsgU zZ%jOEN}RQVYgf*SJhY?f%*)W13taL}oiS9)S#df^-FK_RhoFG!uFg%DdMyiNytG|+ z&#k|&dwhHImVodRdFM>rTJNZ(F#mFX*mo>hdfUb&OGG~xh(|u;xBvIy$@6>mbrrvu z)tHWiM@R2n{yjtP-W%K0di#G@ejo4muYdRN?yq0XzkV@Scjepe`*_&C?$^hY=l!ef z|CikV`rka<^}l%c*SaMCd4GOfwx4HH8D*lh|IdNCicgpQ?f*S~K7Y6UV{spuWv_0$ z`*%s_pZ@)dPnR#t*Z+C=@_zlV%EPC(Z>tNktCO*_)N1is7v*w)($%@CN;&;M>!&1l z{hP=!e^aNz<~0e|H*9IFXPnRfUMxqg!*kB?&bgb z?D_Qb#gFgqZTwf$s`(_3AvMRp#s7xgly&cJO^RH*{`7uX*(vAsR_6Y_k>;*+hh6Yd z(3kIPDo+VlPR%n__WWHFe|2w${*5?xw^E@v&L3a%em}^0ud?Uh{a1EZ3;5-`(h}_t zGQ8MuMf9#}{rxG~KFv**0c)zByB~P{dbLi2OxXmPGOLqImYwN4yYxmMH~0S=H(s6d z;s|>9+L^gr`c}@}t&!Ci^-9y92d;eh`wHJw#*N49RwVkREG*roAu3jQB~2~C zPa$#D$`Pd%zV04hd{6yyou>Q-Mc>LczS%j?31kK2a_c2jzt~+ zYFzW?%!iGaOC~Pgz47B?d&7&*4K9km4O-vtkiLH5E3FrA1g-c54B5YSSQZEr2Pplm zvHW^mvd+Faev;*(J%Y|He7uuw)Sms=dFX)Ow>s5lSGRkx2A5BcK2m+SulC!qrei0k zJj}7~D83?k;ZAUho&EgR-Wm0JO#2FERedm-V#B>Ozx?7w)69vVBdQV(&8X4Wm|yYI zQvS$n&j~RGKIa~)B>8pin7%}A(y0)!gctvUg#|lb8p+ulyU{g&>9dlcGY$u2mdyTm zjLq$9KwIj8kMeI;pZ^!Zdi>j5$sI8_goaRYrosoLq^jadfAMZchb!TG`?NCSK|56jWs!(f8WME+2X#C>8NCD)R{lGI~XQTyrz_VbIap| zc~dWi7bMibaJ^w(Zq)I??(UT(ClV56&odqU7_+&c>0L;}qt8)UHv2bU|M7h1pU+(X z_k>v+*BDtF)hv(wC2G1s_eS2@eGboN{z&7~YX12$GIQJf2Q@i%k~8|B{yt{VZN7Mh zO6&3Y^X&dUd}(Fm`17=c0qcwN^QL>V3fFb-uk^ajvh)?eifoy-d)vH8Z>6uCFni%MBd>bx>YV4T)7Q3}KiK#eexR1S&WU7-K`um)~vbJ z^0WPk)JC6mp4>azGEb&W+RQxPSMGSfOpTvh`}zEXs^&B1{4t&J$2h`7LMQRlEVI^Z zX@}fzk>?hPhDYrv{qN*6=}77Ksqb8;ZhESI{?U>+s|9~gzy8TM{kr7I=X!SK`T{?N zeqW#b!AiY;?&|JOUR!+|BQLjmUT%NAjKBVggKoOz@4M;gKh2}II^5GdGd;auz{S9( zEa1-+4@1w726Khp|P>6;t$$F6wD(c(N^@ zE#13zgZs}@d^^=@0yZ&=YgjSIs_$Rv_^SBRw4Ga`tHK5Uvh)pg&lKn7go<}ZIeh%{L+H=an4{Bv@IMHc z@BH7*=2GAfwwR>L|0`>f)-%8U{;J}rPhRPp$CIk(n?C>eTFZ9-+VqAn*SO%ToKw~~ zPPX|NHCbGidHKSsDY>VoK1&R1d?*m|rSepN!N+M#$5p(wO7o-g?zNs_)a$Odys`I$ zh~(5V-$`GeO?w-rRbj}Sy>5Ml&&p@c_oQ0BPk*-eO>_v$%n!$JrA_D9p)vLFlZhgW zmgr9Us+|yVgH!sF=9O~-%cdLJ+5P6K4Noo<6R>|aVN2Kh31z0ryq}Q z7rlRJ_S@~34F3hSe6#qa&#E@>P%cAV>WA0$O9N(G8}DzhKajt-a`W`lPi7aniCDj% zY}J^5X7R~uF~7U-C3l_s{DjHaWd?&z&AZ6&n|9k?fBQFc;;iKsk?O@C9_+M|o|fH^ zD&=RQbG^bU>+Rm@8&3W-ZM?Xj?LtUY^^dNgw>b{-)fF+tay>a;=lZoIbjjzJ)bBT2 zTrzhCQ)a!&$rNX*TjbCK7sK2_>Tm8_wIBiDIofAICetF0StXrlkn{36`-s~w* zJz44czXX#5o0nfcdoN)PUq%n(jSH0vYMc*7%uAVcvi(Ltr+}5^^$1QDtD8b{hoUy< z^ZQq6ZtEBNkioiO`_`wGzpM(kq&%Bp%uy>J)?{QY+cbSm{qcVayj^ROpBMM(n^*s9 zHMyHury>3Ze{Tge`ECZG1hp>fKmoJ}?3_ucqR1It3!?>Y8pirhe4u$WVNnRXFeld+ zkLE9j3Ku4ycs+fW-F;grfs>)L4;uV@Wuh=;R!*($%Nrk=R3CVSY&1EbyZu=w&yD?0 za?YpkzrnkJ(M(4&Lsma=BJ0%5$@;0bZ@c$dKI>_Vk7>{-(9&-QjJgZx+w@t*EW9QS|E;PO^A-Kcn>6>g(MJUdv~$x;e9N z@=O7TX_rN#eoiYrz;gNI$rEdo=1$;Pzr}E!f%ZYY1)Kbz%y3@paq!Kd3mGf_J-P9H zj@8++RO?fIUfDt=Hr2i9#ktO!IdWg3^CUlg?U{7*$(rSFb^P|%cmBP4Y#yglSf$~X zhoMW432duh8MZd+O#jD-)o*94J677(G&{+(XMw@vk4X-FQRQ_9KFj+0#Nbo2kN$K!_33j6+x?v%R7=e+O1lcjZo8>{JwW}9el}Ub!o?-Z)`S_bkJZ2b#T$j9S!!f5mOq+#B^@+UG#^S?~JXnXOg%J6m_{n`_S) zm$*=`Siomx&~ZMls*~DV3znK&JLVobKgHgCUC!NS9?yzq2TbwU`IY_8npmC*4}UE? z)P6`#cYayN$v-|%RxQ{aBIY}HeL*g3+R=>+jIPEXYvu>BUD6d535(o0Uuj**kF#m# z7V_=8c=C=+TgGPR;~ZHP59_nO1#~X7IK0haNo3V=dU08_cKc4_)G7v%=ab4pJiXST2-Gcsrq;SmHl1io7Vj6eZSTD_0pf2 z_q48`@qRA2f0te7^rhkviwdOoY>|61{m_U1mnxS`<6iyG`*)}B>e*Y)7>0iAS#_pf zzvja2TaOxV+RwccmwMS*YSK>Ur3by{n}%x^b*%JmHpu4Jye%?qf$_JqYsJn5m#W^9 z5&mTHb0b5_nFs0y=Y2Zv&#nF}7IY}STl<6Clm-5tt{EzxJ`c>|*kw>+kR1Q|mAKa4rvX+_F-{y2JOCfOpn}xglqc zYS;L^esKGZ<&9~d%Yp>WpIb>Uobn*ZW_vHk9BYm_-aG%4ADp*(#Rczk=MsW<#)R_h z{}W~yBimV$Vy?!Ilwuch@gC%H3vo+OQ{~~@`Q-n)2aGK4sp=_V z@4so!FY23G-;goo+jd#OCq<^2`&YOGs`#xHjp?`Gxczk%-^&vVZ^(Q3+MAu~z7;K{ z@4npZ)V(8ZakFg}g~d-c*?CjjPk-7XSM9fEx%afTdz@s9jr(@V}tRl~-Rk+27h({Zz`dYHuv}$6FJoE#5ZwlgyOc zL6X1j>^iOJk*3Y~VS3&H6Zv;MYm79HZ&7`3w}fNy;R!4!4}A!K_*+S)GHjX@Pko7d z?2d|u78`Od)y2KryTiWE^7+f8(-G-4YbQNo-L%am*5ucRtiIeWs{Ja-yK?Wk-kN`* zV*e+v1pdN}`TTEg)-EXsvOE)B!28;xCwZT-x+LdM!!GS#U);0gje4(UhMd;kbvoSU z%O?RJ&XYW?j7v}bf5j)T?C8rt^`GIZ{DO??PfvIhXSk>P5KHcB9fA~W@6qu3PFuRpDphndJ-zxvBrn`>E_+wou5 zc8R{2y|uSKOIhn@Zd~S)&a2_G1Ehj?HtuYwGMyB1)GJH&3p3**L2<9AYFA`$23>!4 zIf}n1e_D~2j^TWL!|DCDMpM?$QZ)&fD1Y>BfaP7@r;D`2ERDJX_bKi2d2~?frf}hn z3FeVZshx@1yId>I)>_TTT03XW1*_&vzpRD1-~YvlcuvzSuU}>TC#P=a@{9lPyWOwx z++bYsMNv<>X7XW|wt0`GvL>D3`^UB4v(|i%kt^@T7wJngzIZKNmhok?m&vb#^G#}} zL{+S5b$<2lYo%tlaJG)=wBF|9(PkU?r(4bCX*5miYyLlF=3;}C6>cg2($7fz-N5V2 z)TP<@=|k@nmCJ(HH zPR~ruKlHO&o1K{@t^D%ymD_AC9`x#L)sL|g6pLFG!{5;DDw4|5$V;IGe`-Fo?SWnEyR+GJf1!}`_Ts|zm##boK} zoBYq$mi-b_BVfR^r*G5MfA4#19`Cp>ihdseov&nRE|fuZ96 zfoZ&|QrmKVUD}cQ{9bY2P3w8Qa?poGO!Haan!U@Kq5IYH|2C2KP4SPFf6l&Yp}#e1_EMLiz0>of&i=eF zzIKL%Y}f23u6LH~aqkbZ^IgViz!KAQUf$@i)kpVM$xzp_=c&v(`jQEf_qjedo;q@m z^{xJe$eUkdS;N{&p0eziG@Wj_BSmu{9j~JztZ}BmU73N-v6mfnDEwki>J;k&43JF}+IQ>1FVPmEPqZiYe;(uo|g;Fo9Fl<#iQ^CE}Ir`=O zM+d5|bqYU?J#-}8mgoI?HP1Kd(iPvcWR8UGI`X{#&K8r7mApwYOo4xNOC4$~nv-&z zf;f(uctn0$!%^>iSf{u+=$vfD&*POQYp0vu^=8g_@r2d-OYnQm8T;nnJH-Fj?_%IO zvG?!QqG_{LJ((_x71IG|9yORdww9mBzHXQ1ZnN&BJo1Wv{BJ6&KyxS6|hUZ_<-~fw$o3 z{;DHg>rE2dqH?pIe)a!&n)TF~PT{-0QE?YDC+;!JeNl4KDsGmEm-%kh^)^y3bONO$ z>;w3E!tZa8ivQ@y*|;n;CMB!3G0)`fi!V%igrlD`~u7+hFQ?{>q=5=G;Mr zGnGFrT)9u1J!*~7RM$U#ybja%a4ICXu9Rl`uCi4#FJMA=LdT+g&kkmp&K9)Y_@aK@ zzAK$~_xYZ@aD46WwGzb%E7Zd~PZZ>LyUAx+-H1)(k&uiHF5PtML#8+HEIkVbU#9Oz z4!MY4dDpg7qk~uO$x*)7PZ~;i;~dnC=lz;%KPjRj_nMOI!o7^MUuXy}J|TJKu-_Kh ztvcUwcJH~@(5&|J($}Q>WhKkHMX#tD ze|tF1{AhG;XX&>S@jK%usdTMbQC3iq%at+t)|A(O9~hjR{=u_#SyP`$Gq049o?fK& zk)+VV9F5#%l3J39D>J9;uk3govnz)E^^+K##oua!opX!C?n$NW%~pPGS>AFjfv4VK z{aK^GadFGn`BxR)yt0o&&gP{1PLj7g|Lf6@w zFFSp>Y7;ucGmYk(2L4;?{PTL?<`pVy`+~V7=5T54)}J;t?5A7lPYdgr@zd6an+gVO z-8D(*gmGSQb163LwPG+6r?3)iuv%xLCaK86BL(`q*a>YU$bvvuC5_A>4} zTATPku8GuIo^&mD=9c`#sY1o8bpEoLB!%{<8RUl)zhD3OC3E#>-_rcHu5_jT<=#J9 zGWTrpG=I3Meox@)2McU|9gsgTY1f}ChlIm^x!ELMHJbO~E?32_qMIhysyIBCrE+^l z`R2wcy(>C2;q}~ozV4*Fh`fDzV0L$AQqO9M#S?vg{@V5H;!mEtJN@IL!5%1w$<`aUZ&AuJ{;@Xt&cV=(gebQu}ZXo-zoy*K7t#_#4l6w2= z>o2pk6wCK2fWwx9UE-C3Z{BC}W@zPEOaqSDA1@oE&&W&Lbf-_{lTinwM6N#=aJP?}!3Tx#X6 zU0ZVazbgAM@69*lJ>j)^R+La?>T9l_@7GpedT;sqlrhVrfB!nq1nfNKJ@JXitPNLX zMNUfl_ANcMNZ3lqBW~lNZ!b1|H(6lIU9l`Zw)^b7jAdHEX1N9Tx0jq}&p0$Qc=pK~ zDoL>x{KeXG^%vZq`il04>Sh|v+Uja8emyK)_Kb$!*M0lf&vLnT{d0P2Z3{bp#vBp; z7aDVXUq!3x&j?TMU&)Z6%Fpd}P$GNF^2fiLTkXA#_VJ{Pb1;jieOA9+@% zzfUZdnBH>y*aD6x%lWP1zgTW~%C)t0sZ@iN-cjejb>-4)+RMcX59;u~-%`I=XNHl?VZPg*%YywLbHo{&3H74n$6Humi_$$@wNx75*OSr>KxQQ_eiJ0KW%Ne`oa8T!Lyf62{^UY z{N?V~r}t%6+OAIh$?$IR6ZX;-*LVG}+p1S9@OifPyj`O6bH6>f|KDkyeE{gCEsDvR`&>YvZv_0iU~KPYBn)t>$N^SysWZ@T6xU1=*QY~~sj z>GA*7^54H_wUsJ|9Lid3z_WIx-TwDA@eh3V=e+IyBOg-Uu=mx$*41~X6xQ#*7R|yR zdPU)t5ld?7qKqp+B5S%|2HSpHec-|0W2~A9^{?J+-6}KtamDQ?JKlv%y?N~Q(_T}F z88@nuTDpG!-rZU%CmFnsi|epvUstiu`w1^*>s?H3-I?(`aZ$0Gi^4zm=+AXagtw+8 zHr?DGxDo(uYyb*`{wi&EgMoT4a_6yYWDk=eFnkE!wT2RtrrCcF4v@9~`S zQ9L+Q%Y(Uo!i~iAB^4ews)Tkqo;WKMW1+i+*?XVc_o?R7%~`&inK|n>Efp&WJL;T=aK})1{2vxi(?p&!=oS zcb#+Z-Kn!37zG+nP8JuOcYnuP#^q}I?~1Zm)&`zi|KaMGCKUDTwH*n6@?s~=TGrcmK^z4$7Ts^Aa*j>KaX`ra&_;h-m$WrB<%FN9F z52i0RIJ)GSaK*2S^%+JNN}l?)Jd8c%%+A9jZen@2`0#d?TRlbby_Y6>tyvu2 zLYvXe`=aA3CkyR>c9l^3=i0(vL7%P{HWdcg3rB=3jBm){%y#!OQh3Gq(ZBxD>YbJU z<{aDktG9jk`Jb$5QwlZQ=TH4KXMsze{0uABFDIOXb4xS0CSLA}Ql7AXbJ&!LoPKY8 z`aI>UNr>4iR4_96{O7zwbUmd*2d|dwI5tdD!6p>Zgt(a(;r^EefjU=L(hUsmDM#{R?8c1 zx14a%v;O&v%X*AVCFk~9ui{ggbLPbbp9Owz7%p9r7IFN*v**mu$)EhoYUd`Xt*x9M zlVg6#t9RQ z7_Db=AJY7A&&uFREnDoj&KsN8Pr56;AftY|ujZ1lXidqO*LmejX2%w>-TK^W=5p5H zZOc57^;Wq{o-#dMvh=#AM((QZd`x#F`*WXnY1CeES1!GOK7Z-TpefdecKcnu@jU6} zi`kRbOg%qm+x;`fM{Rt&>ve4`*?7K)&udn>Fs;%%(dpQR&Qs+(ZZ_AvUsxoczW(Ri z+Z?ynSzq22^xO1@*5W0ZRy=mcy1q>ux{uP&FE zw!ZILZXtcM#?1SYj2g>?`>($&*?wW|^uOKpPekN;Z|}Ru_~v|^lhgu}iB}KKH+{6& zq;+Xowq!|VT9;h<<%}cpw-<)4+-85-ZjDdCzenq@-ZWt1kn;&|U6m`U>pMBaXMI@f zrH~38H=}vi9kkc3vZ#<<^_c0_`a=uO1%#e#K5}r<;)~dABq2)}Q^i zIL7{JRmI^V>tL5tfqM`BvEMX%%BBBbT$8&OZFK!B_I}@#w~OSKJ)F?~^mcfb^P<`L zFV2>#91E_RYB4D=by;B3yxp!r-;4K0Y5I6=c_no9&eU~F{3g|BywqO&{>SF`XC#-o zCrZ9}zHt-RLtDj}ANiNh+EC6Nm9gX_*MZF5mf3nm=Vc7%C`&%PmP2RXvZ#rd z7O&X3Gg7o=`v;f8!^>{0zrERq;n*i${dkl7Eb)q%lb?V0ed0~Jn44JtX|FcV-^cL< z@+X~kKPjp{^uP0$?CnFFEqB(lDtnzMdD*<~MOvBAj8I$s7jlnP9o>GY^;#?5z37@2 zYPw^wsqEsF6FD}dE$;lfuuNl@^wW!T(!>Of5lbH5> z@Sdi5TIjlN@EUS8UBx}!N(s_J)+LEV+v(7|++#$N{mbBC7 zkgXR*TwY#eOOF4*5p(8+P`Z<;o2|@cj}uz;H`iTUpdvE$TeSI#$V}1ws{F5-b{XW| zRV!u@$~sW}_QGMW6`ZGP@3TEK5Ipun^JwPM+i$~qmf1;d+|TPUBmZs)^O{PfuP&#> zx}*BMiXP4ETy<7LV|~J+5_8u|A;sw;{%;>`%L$3+oE*fpon6Cs@!Iu8o^}koL{1$S z+5GR&dWm|g|2mTPLe|{uZ6|hV9NG6}+qAIlEBT`0Ua$BPAGP<7_?bl-FE=fD-+gWW zvt4WJw<@J_x>%RrZej9V>3vS7E3vZoj@P$oY&i$pw&ZdJ~L^1*=n%R(<;7bG#WJE{cA?nUR=m z7d_Ye&dJ%;S8oL;z1qI1HzGat(xdlkL7 z*;eAh4u{Ifpk;9@JN4z~PL;6F+nIRy7SDG62_jqO-JHbx=1Hc9&bdcsb~y+C37yJ{ zYQJU{e=j6yWrm7Xrx%k@ec(doZ0p^Y>e@@$Vq!5H~UHLfhXa&3r?I|+A6$h@np+a{J-wyZq4`@a{1qk z84OeRIsN2(z{sm`_>n^h-y(;*pWi(y6xi$|&Ml-SYRgmWclCXP@zxF|#ut6{Ue^s= zONv7l9lFh<6>v27o_3N~{GOJL>fR!e(VT6*6Z$+3PPu>oxsk2JhtFKDKTg~(@iTDm zjpI`Zj1X}v`l%_hxnlA2)%#BUDz0fXsd~QRmZQpfL$+e?W3w%`{cw_=eotg^hq&Xk ztG%i54D!wAH}SbiM1S1v>VJLd;+>OXWa>Bk-F4-LU!k-3mY-`lk8I0kcaR8upPgN? zJw#V?`n{$99QNKi{CR<0rXQo5`!ccJQEr-Y5s5LZHyN^4t-fczjD6t^nPoW! z`!>s-EX}=@N81ZFSz5DrF((`8B4b1O(H*r#v z>4`=y??;F3g_lp7ebeT-K1=9yL*Eo1pKfah$B=!B$GC&z6!K%%SZMz|?;Ny!YgCS- z*V#2OmaT6@qBjLQF&e&f_1K*6y02zchU2;u!JC`Krslsrb@a9HY@-i1x{V!}X7N4s zwo6$Rd-H0Fw2SniJB;=B%X2Q8J)NbeVcXv2=C6Hx`rFH2*Qu-uXK-lYn&zeE41~R@N8>Q|L(%;PWPTqyOozeduDgp1Ex^HfN1x%Zq1h3$Hb3tSHJrn zHa|snbF%-pecH~_nYR-*mrcL@;-+x%&QE;jrvGv_Fp<05x~k@Y^xg&Pmi5c`%;f(6 zyX}M3bz#qgC4K8BEPC~&!C8QpTRnD$VV-+bi}EpU{u+zKJx_k~uh(85(&A#VRDVWR zb=$$MU7c;t$GF1;`$`p0KNYN7^t4Rn@Laq0mE})12Uq-(GzqV;`g(I6PsXjlkG}Dt zdoFL}DX=Q|$|ISa|7Q9m|66K4HJew|cPfN*-}}veX?yaz6)l{Hjl8*Ce(tdLpRE0M zvV&cqgn?!-^9I-FlKdhr#y7&cPBbt08n03I^Ni+;t?3ta{UUb%aM&0q!SH&D%6c2u zUTe1IOPvSpnRmX~&M|d?^R^(~3IP%IH-BzVyb*HT$V+tUgYHRXo2JG5e9Ume#eG@0 z@u&Jl=U+wNop*N0``cNYdYF7(9=!6=bIIDU=%bsGHkVrbGxoM8t5%Y)WM^-n0LEMMdo08=+Gkd_DCqSF}~?dYkFN zJ$ompAN?UwerVO5v=&nt=eN1;L49+kDy?|()LkUHm!;nMy+&9)r%9Civ|rlU3ny~* z?thf1EoCaHKf(~ZGnhA9c&}c}|5tOb zc{k0t>9l{#Buf)HmosAjngoM?v3dkeyQ+8MU$dM`H*cz*bX4&Aut(0<4yMnx7dU<{ z@c#OJdMSrih}1a>y)u`L43G$67dsIlqGq(VW6lc=pQXl&{#hI{zZg)jHM`IG)&z$r zwvTsj3QY`JJJ-`T>UO-t^#HTV?pOP!os|rm*|qfGudv>OJO&Gu3k#W!5b)Hph!cIE4obJ{^s zt6HZxrR?ASCFQ5wH?Jyx#ZLyRR`qUnY6WvO7Vhi{En3)nWbNf3);-oH_7T(eTvE@R z&iACo`eJe7mH@wNvT~1N?<%bQJfYg#ukNL}&kAG9rI*!S1zi5SxA@EEvi{!(^6ww{ zvib7MACB44M`LcY=~e0p$mfJda=Nkq~JTl}H{M;z_;lqsT z`ttYK&W@bI#ZkLz&t3a9_4NfTU&_i>nTURCYq#FxEOOxAg8S3j&hw>8JeFp7@UUQx z{eqA=dz}SYTXYmp|AHn;x(Tt9-aK)im;lHhWoUG>zVJZ zbY-us^-g_Le}3iXom~ng+Du+{5gL}O7d%<(aT&Q@ zU1r3(AwDXhexk#^7*>x5F83KcU26ADK2lj!wP*WZw)_*e(^`(6nZ0=Xx$eD>A1_Y! zt(LEhunhfYDfalu=U-LT?}c^rW-@T|d!79Lrq%RByjJn&D8BmNN4<(ab5DHT+4qOf z?vdut$ucQ7q+R!X?ukAhduE#BnTE2(?GwK79oTZ=(59qUZ~Wc!Z?1U9t=Q!|$G>Xd zdd~0rz3=4jzbn7*hV|V_%R6=!8~ytA5Wd&pLK2Yx3Sr&%BE6m|m?qy-Lwf zZrx(_CEFCvU99G|-tYNlPdumfUeOJY&s{s*kvZe!{)8F(r+IE{yp^?bvx0q1`KG^l z>!V`#m1bYI-u~&`y@U5MeM|q|%XQeRJ4++C_x~2P_q(~)pJerYZXf>0^nT%#+*!}+ zx5%92)UV&l8Fcx>mKma7?;Z;~n=US&^GqaTPH67mZHxaru_+D|+TK%ibgEGQio?PY z*Iu66^Uq;@P|_lu?)5It29n#_%y@(YuIXvMJeOHA_kzGto8_g~zboadUJS2wo38va z^Yr=oaV-lTZjJn{nYJxJcfr$j6YlaYmhM^n{bOEz*5!ozJJxcxuB`24LaZtLEB|E+yvWeC@~ zti38X?-sv%;2Wr+nVO~dDC9cysIli zCT^5l8@774>ei_GwQs}M-~aRRdHnxB*Xyl+J?NO{?xCZ$?6#8alEZ$?j`?bjzU5g> z&iZ$h-)VVU;UT9r5qZa&*lcaAbk@%e@@b!b;zImyoBUkW4oP#X)RhyT^JuPmcg#3Y z$I!fT?Sh#SDQmWx7#!WrWAyE-;moR_$KJ8b+Ey%U4qa3+_!PHS_HX@efo&-*;s+ix zsLXCYeer78A-3x~-h@Zn-8~&((0;hce#f4DpG5v#bPlt6bocnp0N>`d>nCp4kv}ob z#FQ~@_8;r6jk6v^yB2P~`1DCv)G_^>nE&(R@Ep5qVJ1+gmX#ImJUw-LKGBmnw z_uPNMu@fi4=X2lEWM4N)$4;$ic2E5#em2Hmr==$cpI%~?s&UBu#><&s7JA;V%<1(F zVvn72K{v}z)+UKZ{@EG!4Sdpv+beah?o4VtGuI~Ij^PchE%WWx-N zddXi|U7p;gtoL3XifjL!V%*?Te1F1%+nmosX0;!6anTCC{+xT^q6N>BLo~D(^IE@f zO5$(Zqs*;&<$I2^b)dwf15U^8h;MHEe}lPWmrTy5rxv~yb=H$ieGk65obG9$R9gF1 zCGa=z)0fOEoQgahw71vOEI_}u*ei-kgsHw5o{5X@_;oGvPG@pjVZtEasdoV@#>&ZqNc zj>7R@ogG_R>s<<_Z~b)qd?xG9x=7>yzb>X3txDCr`R~`oWkRW2*UU6uU%y2%sNQ?` zr(e}4zJ1%@bv7i^IqUh?`SpKg^bE49GUsoLuQxv(x$6J>RS`_=#kOn*GzF_onwp)K z*xd~F+PCnB--?U9(XUN=KAvRyE3$T_kJN>G>AEX>`BZHb-rQeTe?8#>|$V_E#cHQv$sxQ_0F~b zuQjD=g(Qf7n2>T!`-sH}2IJ55)BD0dT%C7ji+PDy+KRlqWq(}m-frB@8?aZ!m|rII z=yV$;k6)Ra8G0^FFBj$hTId=c6}>JvQtVZbetBZ-{yqB^9+NOJ#OgbXHl^&)_?`3b@7^t3)9lnvmp<_6G_3DR zn0{6K@tkFgzg(L!HD}tYC(Xb4E?=+lT0E(7-kmLhEVX%mM3-Do7T&wq=lkT~&4+95 zrxw4oZ0S4vE5&{Gi6cAp+@|ytC7Vif6qh-*vljYIsJLUeD(RW1w)x~H!`afpJ-ya? zDpv~kpSt|S`0=Hw{u@p&y)|iDW3L9s)f{=*P4y>QPRQK)Xce6^r}t{s&9fyR%&M+m z*eADP<(~B)qm?CgH|H3evd?8+bo#9}4^QFGS6#g}lDkv#{@wfkx6M-ezU@9`&2bbKN#>t47~BTes%3eeH|?J}H=QT=Dahc&N0?LMBPq zSt&^+d8th$Qp?n}Sy^khB-z~d*IR5I_rkrx;$7k6<~H$51^qJeAFmy`bT-T9!*ia5 zMSl%_-dx^Obox}L%&fUuBBFQJ`Q4Y$mdp5RCaH5FIHzqw@a9$Z-^`|{tz)W+Ty**L zl;%mhwd&;_N!44WWRyu*eq!Hmz5mk^`&;404cEN3UJJRuz@h$!i+y6mv;!?MldsKs zlDo8~Mm6uurU<7Br;kf6zrD%vt0Jc>F}q?$_tn|2Z`TT>4H_n{kSIhU3! zxa@aZdw1oOjNF=MXG`Q|zf7#({ag7_)v`w{j|*45zZS)^iEU!O)Ye72BbV+iPE`8& zIZZy~hlLzZzMt8v)-MdV4X0F0iSw>6S!#Yo-u%+*7yUE8=4 zJQI5IsmqkR?KtO6k-P4hQ`mp?IW#+m1es6Lbx}x|=h@Tqj%R(vwk6vej4ow+U8~nT zAR{52<~@shQKR*ds0~sFnb(#rzkVy*^wo>Gm-FYCz25uf!DjW#mlsy$t-8I`a;^Gx zOX*AbOHM~geX6~B@&4X5Qx%WBdijx0q_e-g?CVM2#fSQCAJedGVp_J7SK~*^vGB~L zZ0AI+TaPU7TIgDL=ZK)SmPumsK}JS_h+BEaW%a);Tvy36ORDakdT(ONTc#~XPW(CY zDAC%l{jC_|ou|hh@?4jE;r?KQu+${$?3s;{X-)12CjI7>O;43p&x_6OmerZPeXXQ) zdHto^=gu$O#W}B8|Nmt*xg($6Yna9+>Mm_#-Rjh>dExr|!y+PA?*|2{FIdDUBwFgG z^~!Pe3g#14^%GuvJpGlUO7#4sXUBN|o-^9a@>O7~ZOE!tVZFERY5l2dHEbiIw|AC{ z)s-gvHjrX0j(5Mz>yrMbySaUZ)b-+!MGacNo4iEqzXfzYI$pQ*mi6|l_rw=}`!?Y< z|I+UYH(S4aQ@y=1q_BPEnwW&O-z_75Mp!WXV!4#Ojg#-U!>7;nc2ni66Z5)Q-#r!O z=)dW4p^LfY#pfc$Qyo2xr-CQ^&wS)0G3|7>uHHwk17DJP3l&dnVKCVGY0@V_=a4_T znLinnK3Yzk=C7iwKY`hP@$NbNG9B`F*!hm|zYH&Yz&)GUS>B@HI?uFz_V~0bcazPe zPR!fpcOmA@y+^^UcBh`F_td97Jigc3RBCSj-mdA}v&$qN`bIb=Ea9lxX|s&~==ljh z_LXzKj`2!xkGKEfR4wy{{VwaVl$70Z=gKw)`Om2Om?pWTZc%}_D90DA)|qOCr3Neg z_oeQc-gHzpj_JhK-00Z4sK?i@ua4H=teV2qc{_2f+22KzdQSe?9aix{T>JSHv!yqF z&AQNB^=P^G-SVkjBASPfOD|APSU4~2hp731yj#cLH&oQdvTfQlOYxH1CD#jYo-AyN z{y1&2VZKB?|Nh$dMJxQT3n*lKeG>fhWctkE3s&wwx2ft~eq7wz zFPG;0*lLsXMlaUgxh%5(M&vS&Jy+}&vM*m_r^8iSvBa+D`m4iCUcQauhcjeuFPpOG z?fAJ!o9VmaFFj~iE9QT7pW$_!RZEfcbrx2U$!rxn zW{3-)+L@F(`}dS}3tdD0@fm`%)zTLTQ${)rPXMy)BI$O-|Dg7kNLat*Y3SD zbH4OMHLoaT_wL#SM=yNeW%v3=-0Af1bx+M+8r)Rl4VJy^82NVMnr*M2udTgdSubUO zzxmwpy6szU-&r}i+01(7_Sx=tQy)cbkEoq4v3nn1^6|8Zp>wW%&NiI%M(OFgxKpv# zTXt{#P@&avM>FwSg!hwqe^Teo5@VBmwc-2H8?{$%$VT3f71neA=U>Rww(Lz}@_et2 zKNf7uxYN`wKBMN`^+%#cpY-Jyv4>0(W9w;usbIUL zS;g7btNLhQ{i7dN3nD##D;_>k6xMa%;mzgig1G-Shi$)Zx%b8UYZt$Vo6DWfU*~dA zd$)=G-pzr5_sh21<(d^}#a_LzDJiVld*RKq&)U9Rkh;Vzb?NX^=UG*3?{DSLd2sQq z9_z1thVjw+_c|H#r^u{0!Ed&G=D+sL1*N;@ehK{cbk4^2*QfDH)OYK+-Sn4Cb?DiY z{Pjbv3P^D|h=5sF{Eq5t9eV^R=j@{|qjj7|xiKka_c zidDJm-mO`+J18hjd4F5Q9|^havec)n6VG4!uwSDf+vB`RZCrPB{F>8ivjvyW$y7hG zC1y#4_r&A3#OF1Kw=QUuSa+DEzO=P_>ofk3!n=)h-=CVZYZ2EAcc*-|!fEWKuA5Ib z9=N@$-$0z-#p-DKrvTPP>}JnC$1D|8;bVC+bv>hoh1|Vup;rncX6mnP^sfyR)v!7! zR%>@kndPnD>dnsE~;o9j`Fmn*H)1o92$#kDJ9#lm>2|m9li6@7C4_-(QCQJY>6ljoO@vr>cdXdcQ1g zcxpEBufOXzj`}AYCcC}~ubk;1Uz>A1@%S{OBexFR-|jT~<*6TKbCcg+kyYLH>+#Ii zw*>Wo9d9D%9`trA%#jmcIvt&h$N8rz%x9z8XbKiQ-b)n+0O4V(H z_)4{q^fwb98K`f(_I3HKgb8vyU;aL+Ilj|q`hSVGn6RZwO3(Z9?|Z?p^orQMea9bm zF|EjoJ3A=j7hZCov~`7nozmb7_7 z{emwKBen^(3UY|Zt<>;$5PaGzGJDmjg}1!hUqz`pn>un7KebGsWPj%Cn|+QOIW_-? zX}Gt4R^n+PWwgtapX!^^F=dd|1qS?}!WFZ`OtX(@R57Cv%>?`sQ5d8tMBJ z=L<}@s>Aa_NnJPJ=#redS)i%4Z8U#!{EcU)c3fJxBJ$);tM&8d-_%_7aQipg*Xp5l z(b9`$a!sym&!5fPD!zUGhy1f`5nnHSS=sbb&hV7ZwLiy?L|u8iCA6-cBqy$S~3WKS^?aLZ$w|Lt94;(D|ko(I- ze4p2$Bg?){le7w%VSHQpspJ2C(RJLuYqZN&@5#Lu_Ve#&*`A}3yRW|fKI^#p-!{t> z@8E9+spl)x(gOshe0JzNDf%;bMg8M52Ttu(PrDPUc=^ha*qMGiw)1~Dm+)3*NBOIn zb5~q4Z4kSvT>7}qfwgYI9^s>MAy+d$Gj^Tad5Qb);&cD}mKR5)sr7BXu;pS_S@*Ns zpO~gS+{V;U)FyA^K*Uh0KBiYc@2e4P4n za_-;MdBIw7+$UosD%1En4hO8XmbI3;Hv9cmsd9ZIzl>d_d9(a(eSPfadP^xz$z!kn zKlz#~VLy8mSKUhHnRr$1FO)OSD-nM7TQ496on_Ay@Gwn-s`Sx_{huV+DAErM2@vB9@KWz3F zmhCweT**wQRwOj{ebMuES=o5VVE@L;S|Tf1vF*}==OuP5DpCmD znwvfM+rh@U5h>EM>-#??G_5$~;n30%^jSP|Pe_X7DSZ`!D!av?_e)7-(KXu_x9h&gO1z$%_jt?JWE%}HuQ^*crxt7% zTe{|!KF^C85v6i#53j1#n0hCuWbR~*88ZATC-%*EJHx#6iO-<|xg8nxxl*eq@}&fK z$NGD`?YZ*hw)xw~MpvunU79q*dHUu#;p_iL-fpX3KW+LQqx3K9l6POdxx>=@pF^8S z^kKc==C9{{SYEJijuKlQn0xcVh66%JKW(~ZurY93iP7|l5A?WnL|hIhJn2?+|8%>y z;jU%+#F$C;t_$m2F3x!V`9fDxq|vVW(AJIvJJ$Dk>4emMQiqE%~ zE4?{qd0k!Z6)S7P{dQ;m zKUd$fAtxfXLd)Z`X6dSp(@gALe-(JePcdNBV7=!s{h&`vp-m{`rAOT}{n*ycO4bNu z`@Q|3$>c3j8D)!Sxk}#1UKTSyMX>kABAxTg#Hw|)8%vV!Zjy;|yO**#$#M3?1+uOg zg*JL!(or1kGQV}2I&XLCU*GZlMA>$e^K-NfA8k{u-;nD&!D_SPM!hXRwG=IPndxe0 z@U!i*(bb$SuclEK6l-JN@PeDQ^}N!G;HQ4B{VD~*zqp^@Xcyw0pxRQsI{jqJ;ah?8 z4!>I@#K&y&NrtWBWBUd9EnKbq0UORMzqd$=S9-6QRDJc<(&<^#KZoqDapd?tG5p52 zz5M3e?}f$I7}Rff|KYQ<@X6=!o9>t9H=Y!~Iy-IX?dk)L2&dEOMdQJF{2Cg5o=-ZB@+BtE$vKvig69hNaeV&-p?s6-&)TnHXoN zF`PRyu}QN=@l)&CZ&&uLF_A4!;Z9DtJV8UwC^xgXd}<}*!M)$l*1tRP_QadYoxe3S zt{KnLmTOS@Rd%N@B`xx$pOToo>TX-XYL!L$Z}|Rf%GcVadis1@o_3QWr;|#S%42JV zyeGy+?{^0uWqNa$dm*n*aBZ;7rRVNVxpI$LlqAGr$4)X>--*2bQW~npFEn@TwbXB|- zrP}bu|6iK68T^R>e=odh6UJcjNBe+QM=(CnZ2}rApu0|8?nX{7f|`if-*azjt-)Mvq5^5@;%Liv^C3Hm}hzYpLSu z`mRgUI4ad=Jr7@gl3g!?%Rk(6+V{}Y^#$**)$p<$&UZZZ=uNCi@9{vn?$ZftxzGQ8 zB)pIFT2;^T%t`y6MT*6KT5z{M?uYCCmFWp~Pv&~hd*5x*zxbu6+|xUoxsK^Iluee} zvgfnqx%F}97iwKOVbfg6y?<`c^SIk>+sp{+dj>$!I;&bH(;&tKEEW&2i- z&9i5TS5#~k;h%Ur{nYxOUs?UPFD$(~Tf-~;+>O~6lRp$qT5hvzTE;~UhE;2;YeiG* zt2<ZGbT-MRBtTH9VfIm5qGCTQNlu2jQ6 zb6hh^=5ACGk=6TTvH#_9;e6e%reA8;*zzZ@FrMwEZ1;ojMEXN^%d$7BcHM{Gn)K#b z6}r{$y&}KlU}V)fql}_SYS;Ds`}p3!+qXH4jjvum@v~~jOqG@GvY$8HejXi|e(I>| z1(EwVE*w6&=S9!_-?cYqy*QE_!_R$R>ff5oA4O+aZ5+0rRNtq+$GDeenp5-huxRHN zFQ<~-7fdVF#gtX5Ccby86qzMhz;>GNl={aVS9uQ`#KwOQTJd7DVa@5tt_?=(3V&@l z<#d3>L3sNrv-$#yAIqeVObog8IbVO}E8Ptaj7yGuI@j`iv3ADH)A36mWi_y|F{-j2 zJYfCUVzz6*(ce?cx7~lkKmYCAcY7q}&B>FWzbV?OXo7KP(gVHgHv7GfInJ(P%v-&C zS)J8SQSo~_iUqqjsz1A|xtQ_So8YHY{cD4-zJ2+{o>{LX#gWJVbbZ6JNWph&uJE%+ zomu2RXF|XIzat5L+wQ-8x$%Xez>yp4Sl{}J9#!9}aqMl)sbbDKe}1YTxP909hV@$Z zfNi;r6_KnTcg^GK3bi~YsyDqm@(l0izh&v^@1MAwx6n_E`Q&tmAu?*qpUkJz=I6eb zzhWkx+PNU@K7(+Nam*YIZ^mYw`dvFC7fM?m=WqF+a<%Qh$dBpTUlwIPXk^|IxA&#J zX^ZVn{^fs+&K1p@_k{DnW5@ZC`)s?*7hM$PFG|ec|NH2(y0UBAxVJT~d-|{N+^SFa zZbj|0(4V#Q$Fa1ipLb)s&K%nwZM}(0X&S>ekkVq+$!I#h)@Z#cf-qUVu=mm0&{r^&K@(rh}T<@~mPoxnevn(ALU zpPz4Y(KSevl3G>Y{m5wEf+^1*&v-Fec~0K+mUWxLS}sZbk*;?=7aww4_rQJ8(@r43cUCZ6{g^qrm+c#)_uAT-YM&)bFG;Fj57c4H^_*`R$hCiWw)*7GuSyIb zLIX3-Wc}TG_m|`Zw|Ccz*M9war**3Jn&fq)eJV9#e|GlAvlIM#X3XFdE-#N`OLn!| z_wgBzgfGwfXNgKPg?eV(5Hjep?2fp0e0!n?li!WkWvbVuZl2DNdlqiE$|bPM(*2t@4?G?)Iqnr(vc$qQI}#Q% z)gP3<(`xRuu5mfThohHfpWUo|KCUERdX>c0jA>R+?~8Po%+QNoqJO7t`Gz&0e$JTu z$<()@`9iRdf6-Z9*Am_{GWVYRsX7+?pi)!*+``%e!h2da^6zIVFc9AJxpTSXm5Tv& zUVEeOvcCDftXUz|@3Z5XQ@!k*#=h*uZ6W6_mv8!6udr$6f$2$a%)O8QTX$%|x=ZIy z-ut+F@8gH(EZRv;2HGf-;T66m$;svk1rW656#$D|DenA#%)Vk zribt5|2vmg>aS;0sK=Q*wd;hTZ1u|2S8>cUca;gBn*ZlW{T80ZOF#B6+#y-5?*Gld z&(Fi9sAq|oT3vis=bB}ek7jO}xW8fRlqKf7?1lDCP0U%aCgDwL*CzR>=hGtQTTfQG z%j~+KZ*_ok3TN`4HP!3VDkS>PZ_KTq@O;rsbGiGB-r77M1v?``GKER*|Z87|X{c>aAu1_DR3;B3;)q z9`k0mSfh95d8WJGnupzgCtqIt_8s6mm)F#k^fYf1{H0mGC)+#y_`$jJq^rNEn$-2*(0u4@ zvqHO<OK-EqHusX74EId`I4Yl-ckhgy z)uc<+K{m2`QvwaXMa?2sZaQJTqSY){G6A$%jf6h{J4-% zH7(-LiJ*q)oqKh37uQEm-JEm0>UrJv{om)^t?R1vJahBB^jZH5CZV|+?R&o`&1;^P z)v(ei*m2gMD8E^2KB!(xTDpjPzx-me^zEgh{l{h2-l>|*%DN`taPrdV_3N26xQZ zcJEYR+WezWWQOFKo3|yNm7H?FqB>KiK9TE7*s8F`JL2}wpR7)JpH!w*f9u+6t3U>^ z1q!CjS4$7o-Isd%T;h50@n_b*lj|Q`+*1C?oAFEGiTzJ@$1rJhGc4V#tYG(bzfhHTMmtn4^Jj3?9lZVw~|?e`CEj%f;}#OUn!s1di#< z6zr=nTc=cblE1){V;bai{Khh;BXuM`kn`ZuWQYJHcZxXbPr)zVj--*4D*EB@HN^KXpiolX9~VTtW-0YC2PX~EHz zmL(5Oi;lhD_P*@*g9QOPG8=y=c^2J>TogH%bzNKjJ8tV4%;n5GBaG%B&HOrf)3V=h zLbuAfOEvh5XSz!<2Htw|y$Y=l-eNVQh1=a^v>j-xBi0 zzkOz86uNLFI_%x1i7R4CcWkcRvANtK_s_#?wU;+EJ$fVA*3!V&a9M0mi>;mW0)Myg z8k_k|3IAs+@7@=1_`JjW<2S@DPdb;>OaI!wSmSZfE2+MW!v5QglJ$%F9?Wn5lFGpH zj79q5l-;R+8de0jGl;78n7sL}A0$`%BDnt;pUoU0!L7`TEWTb+(#bkpQ*bMw#pcS7 zgJBK#uD(wGye-4MdeM`~S{cS`^{-ipckVuCnBbQ9gSCIz&#UJ|cC{t#8hLdL^JM+-Sp)?Vc}kY0;D&6W>0{eBeGw z$4?_fq2lSU(xSKZm22B_G*^krS|8XNAGA(aYOj~of#=VRd#*oAj(4x&F#mM@iu?7{ zp4aR2bJ?AaDb9Y+S>u1G>~`WC_C25TekatI|1SCe;b+0`w=cUNzPz}4uX7r!Zn5N+ zIXWDHVvbY4Ww9UK^|1O@%D0Gw*dIEwK0>zAZ?^U6Hh69R(42H`!Ib*lGg&8{$<>NG zR9SMtCG$|4r)1#o_N#)HAKxC@I%BU^e(Qx}2QPkpcrkiXgUsoQSuqX7#xS{|IhY2&QGnh-y;Cr`Yk?asBIrJ2VLe=D$H zS*evDyrS>%7KRlcQWzh3uztBDT~V*MD7QrZTHR-(@InsDjd!khmUDl4|7X&(Ee1Ed z&7}TK%*io0&GPBqnsv%nniqc_$iJ{AWUKYkTbESMT`D%3mhnVMC}HIhw%Z&fzb7%z zyX;dNvbO)HikOVbT1o%FkLfSne(%&ekykkLQ$xC?!H@ITasD-6j9q%Is^i|GSpqh)=QlH~nNWXlHUIa`U#G|CwjK#H z%{bV^Q*l7PG`jA0PTHo|;EPH9vzgNCRd3{XP8TwYQ|o)Z<^#{? zMX%$hm+4k~K2cI$y3hD_a!%>A^V8+7JQQ{QyqhKR-sQ!M!@vJtH)-kB?|lCK-@p5X z6>K{2q{-=LV(NRZVs+K;U9;AS+GzLsUfUJ+tVZ>Dh1K>ucWPE{eCV*KVUE`MNr&1O z-Fv^XagW!HE482Nvw!xM&3#fV{irA0KTI+G=aHvBXC89iyJmsz9$y_TY5k>}w0C#nPr zzw;WdzxFubH*->I4GT|i^>&3jOW!}zVGFBJS!UifJM65~7A4-voZa<}3Cy>r8+0D1 z;G1;b=5A-eUZ&QPGy7!@`k8eG+j;KW@>hNK-o{FXiR+BjL0?PmRet{V)617I4 z^}p?*Kin@b-84=;^S?IbijPf3mu|v`|14AY+Wyggp_603xH3;PfiXOXv2u$*uC98$ z!OrAEGW+JLrSaBCRa=)VT5z1NS$0=@)m+tHu7gwFT-p9BU6Z5b`rPWNyLQ-}$aJ-s z;?feqFz4gfOes#w<0`8f1SEXB%kLL`xW?+Rf2rB}$9rlNw)3za?YppCNaJnLiL<_$ zHuZ*2_NtxOeRe|grMnEfs#pCua*L&ZdS26X?dkP<;&win=WE9P*-HM0o&K5D5Sh@` zX)*WjUY!tpKkD`F&*ye8{yTT?!k~8P~x8IsLZJUpa+?}*AIHn}w=z@=`F{e)Qep`}Tgxr;gncdb!B zrno%b=#1JLqjKkoi!3hBX){L(gpWE5vug?5OeMjtuSUIcuoO61z%8g|k=8N4kTOTMo_wsjFx&A3F_9l@pC+PiI ztN2b_OxOB2d-w5@Z%nox8E(eXGGVUMULM`WDz^ENd52-4d)Q&qTsxhRhRLNL{?%Kl zlxK9zTOzqm^<5*&!?`zwgRF9&sF=BGYd6MMxVO|A0F zz1Nc7JHB(=wbGQkH1qIf{}&yedw2HV6xbtQW7f3%OuBGI)tk-QKQ6!inbTFj+iv#3 z`}=?AaI~f!2rA8*`r+G*=B`;w9GAo!M#(!S)zACBe!XLXL-zF(d%8D=|9R#+C7v~0 z_OtXoukJ*Hw=d@F_{Ys-nauaE@xE*Hk5e{@a-y%hzaClg!ZToB-~J;?5?Kl#w(MS( zAGfDOobOiA)V<-H+g`tpI>h?)|GRU+{ttC+*u=i-%`mxUwLZzv^N#ua#UVTLJ6>9^ zZ>X2B{&=XheuIzaD~kuSrf*NWQ+A|d+T8q=9u<3nR(e`bWYFB#+H$`uYO!Wc{aTKH z=Gp7sE}N$L;!0lamxMzhapKuMWwYdEn(s|=x$&0!M$MIF$|bXS1vZ~QQfdEI@K9`EixS4rx z9er*#x%ioY^5msnhYEcIZ`KzvPS1bkwLm*`i}{3S+fD2?Wf!mAb^VR&O9!sKT#h{F zrzl-6*~PN6=lRt-?p??HRwwPxV@Z9kb>@JoS8-sQZSe8QKF*RI>R%F!BA@~vh{ zNvUhk`k1Y&5}P))7Jo6XH2bW^b#ik0k%Rd)`A@=Uo}M*3d2zx_Ci9#_UnixWsn@)5 zYE4IguHnfkZ?`^LTztkxaQ)fKmWM=l-Q2AsIirnVtLg36NsUccR{y%AyY%9!C#N1s zRNZ+iF7w>!4d$ws)<{f>WSSObMp;(t= ziQm7~Sw%vXmtv0P9qt#{{@3ET@Pa$t9MV5-)t{?L?W;vdPGb{?A{9GpI)dxCt3f_oFOy3m|AHRFbQ@%Mx^L4(rwe$6D{gb0} z?(P|#sY3JT2&tQ@=FJhBzVzdryK^l9VymN@&81nYhBGor7K0>?x>-$}1zoz!%!LpUQ^W7$1)>c<; zz4ui44uiw-#p*|QofiJsp4z*qNxz{YMLJ0LS})JXJ*6Ry?{mwhYy18mjeNIh7 zU8LRj(@#D{*8d6k{L!P{X3fut=4NJJT`MZrbb`ZN_Iy3+_&O zyKTYI&HQV=zTC6)&ut#>+5=A)bg``c)^=3ojR`NCp#0RAZ~YHC>KJ6dc{lgAtXlj^ zHJ__Hes(uR%1X-XifzcA++_XzUCL@nouyOjH}SRlL^QEwM(8?c_6?8Nok|dfc6;&DcEhzpnW+nJefH8^SR|dreCycc6o%g^8~VMTD=cSpNVeqR(ETJ@ zFnJ5(z3}>sJL**%G7_cFZ)x0ip=?s(4WqBY&tES6{N-N9hMgk9A8!cGd$M^+=*(>$ z5`C3dvu~J8?Wi|ddH2}Pf2*oYmKw@fKe=|9d0}M6wuq8lVGT#@&n?bmJH7VT#M%AX zyXHK9V*Bf?ub<72sX@uxZok=fmo4-f|G$ShW&6W~F7A|>_L!~SUC4`TY2U+}y;7UA zlcGQPR7U@Kusi7Pdj1us=gv{&U2t%fn`XnUKkRusUzmQ`ko@D*)t{fF>VA}QJ%1mw zlS4!!I-2KdU-tW7WsO0bCN5g4?mzF#wd%Y3|9|){Uu|#y>*Kq2_x`GWIop39-|zi; z=d5v(N5xw8^J}Ip$`A$UZ=tIZLdtcRd@di^_R`PBKt+xR&Zr>cE?@o%A}|@ zD>rZd&r@IX<#hl4KVQDP@3;9UeM;TG>-oO<_4&1F0Xsf$JnnqbYB|08V_ojb^Qr*b;jcl7eQO?7_vc1-M*c>Mbn_rj3C9z&zJKeo6`RA0 z_Mg~NYrucJ>A-CmK!=Jd<3eEcBR| zXd$_U&mzO<@;%Q6|j>^nS85&G4q__Wh)v~uYQ}l z%U@UQuhsTmm1RcTvy=9{$+TImTs2c$CONc1l{0I`Yk#qg(Y2;qS7tx_nbRkGAWit% zJl)=-8CLSeUMeSdRIbrqBjmSeySQqGn3slJZS7the^tS&erDR&4-U@` z@o;3H@DONlHvy?^r zm%0Ii@xiT89FCQ`Y}1u?h!qw1C21TteKH~9l|a}no9$J*G}dj=m}IoL_T+5lAT!+! zlNcg`4Lg`qUkmFndYUg!o946WZvBhDlVvvVY!o(bTsiLv`w#VtljW@cUh~~$EXBRI zdWKBe%aG%VNxr2z=~3yAjmmW|v~1Ft^LWkb^}jDhy>D%}U>*z!%>adY2EQA>e?Y5BtT z^$AxdIF~N+DP6TjU-`(ik0R}iokq!mtbhNA^0Zztvys$N)IPD)Zev|%>4~VPC0W}# z563RAcyj6Jau-`v6%aO||0p`Oju=h0rF zt**-$cXFOqIjuX*VBe+F8ceDzbNe*E$Sv$-XKSu!UnDLjQ`&utZON7uFKtRUFXRxN zT^GMNJx}+;k;n&}x*vEV8e$$SHaP6!D*WT}WHUqCMV!(bokZ`l-?(&8+q3%~nK**mQ+)B0@!uU+Pi%yhrySvK7~LMeK8Z}EJQwzcY??xcR~@7t+H zn{P5K)NDGsu)dvdJ!9Klc8*2d$+`ucpWf_Xl6h9N?ra!uv}VTV^c|W(+a8w`n5Cbr zY*0@ZOc50-PSBruW9v?l8m3_BjV(RyOGS!OrIkNj*thnMN9@k(V|7ERv`FWqXn)Fa61c=pLVy(asKdVLBR<`d5Dx$vysts$^DJV(lHwx_(W zOz?}}T66MB+3z~2zM8+YCt2+~^A*2!Y~hV%bK)~^b3`*=`!p?PRk;5ly)EX&k}YQs zS6G;DG??S{S=T4XOQ%-3agvCGZM0`ox9VZm7=ePmTDKp4Qt68iDX9w`cyj8Uk&oqp zP1Q4dyoAN?-d$U{K`=k3K1Vfemr+Ff9E%v6zv$tYzc(I*NK0Q7ZobVedS-6>vW|Q4@7_(}naTd+ zaS+c1j=q|(i=KLCAN@Ec7UbzMbLUFF=^nHBC;U3GX+M`_f~zmv_fuUH=RVz4KS4x! z!T;XgpTDZSmI|HP^;MwoBcs4!pGbvpR$ry3$2!$st@T^6*ZS$XcT;Bnwtn(%N~_^J zKjj~nt=~_dXqY6~Q#WDKE#@N)k22kMhcUcPU3*;5X1~siIQ{9da!P6f*)f^dHYUYe zEeMPH!6|L&eSe~n+rGmrTV_o3G;9|8_sXgM7;_tAa9;0XH=Bjd0*imoi8N^Pte@j? zx@w6=g-blM!2eCl(?+0fy9<%grI zE$aO~G2BvFx$tMl{!Ph~rXIU4J;kptN=N(0h0XRFw~nh!J;Jqwn~7mJ<2HrlmTTAj z_c+;fh-=kz?aaUIG+SCl!P}})N&QLdwLXh3Gkjq=^l$*=nZ9Vg)-dAx;+N_Fgot}}8%gb+yvFlu# z63i`aYws|xH;nDZzXa9xqVsNftP|F|F8L81IdyqVTkCXkSJ5pOYdkWv3U%JMJ zbLA$Z2i!(?7KhavA8tZq7@)}VcM|iS`*`_M0xPd?O}Y91_3n15ahFVvOqt8+`G3D0qqR8CbOyDa`e6I5Cp~XXaQR(tI{u4%LC zOX$X~2M4zIgiva{fQ}uvabi39544hDb$nDU{q&+$W)JW;j<*s^y0vs%RgOeHOT)oOX04$ z--LJExA)Ge5wp2_|LVLL(SuS&=7(3NOez)Cdn6+^|C{^bd^>Je%figyr-4S|mC1Me zy5dY9~*3()Nz23|m-v^7(h=Sj=&}&lqp9lgm4eYdZ6u4U=ot zB_vdjJO1{F@p4=d^`|NDUc3v3L&@6}u3jdS*Q(pqZ}(!H$+bI)f4vPu*vFan)%_#S(iJo2Iv)Idtf%hjj}z&ZazX|7YtNkK{KxTs;~n<1 zOiT|?Z&zvRFR9-$b?(Y!5gohmJf0iRPd;K$c)hFf=hr7Eg&(eu=iIX^NX)DG%APY$ zGC3v|mlJY&R8*cfs=wtqpR#_%&OFDRGJ7=|8voq+m|uS|Xz$v!KV|GW$V_ z@0N}OyHX}QXv)=3RaE0z=Bs@3h2>oCyuNL-�t7|8-=kTDo){mrk#l{`qG0jXxLnFt74` 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 diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index ca3462f16ef..128248ce62e 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -1,5 +1,5 @@ \ 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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 \ 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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 Tr$>|i|7VsK)IMT*goyzFExrh6 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index c2063366ba4..d7c78d557d4 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)})}function notificationEventCallback(e,t){firePushCallback({action:t.action,data:t.notification.data,tag:t.notification.tag,type:e},t.notification.data.jwt)}function firePushCallback(e,t){delete e.data.jwt,0===Object.keys(e.data).length&&e.data.constructor===Object&&delete e.data,fetch("/api/notify.html5/callback",{method:"POST",headers:new Headers({"Content-Type":"application/json",Authorization:"Bearer "+t}),body:JSON.stringify(e)})}var precacheConfig=[["/","7f661662cbf6e0eb34d0dbcaaeb4a222"],["/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-49ab2d6f180f8bdea7cffaa66b8a5d3e.html","6e6c9c74e0b2424b62d4cc55b8e89be3"],["/static/core-1222f00ae060652376f7ff0b48470e43.js","b8ee2b61d1908a8d154b7eb65d09eb9a"],["/static/frontend-fa112bdd88ccf8aef7548c8f56b4ac82.html","2ce283a31c543c2b3dad4acac3b63839"],["/static/mdi-710b84acc99b32514f52291aba9cd8e8.html","149c8eaf6bb78a9b642c7bcedab86900"],["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|manifest.json)).)*$"],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)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t).then(function(e){firePushCallback({type:"received",tag:t.tag,data:t.data},t.data.jwt)})))}),self.addEventListener("notificationclick",function(e){var t;notificationEventCallback("clicked",e),e.notification.close(),e.notification.data&&e.notification.data.url&&(t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var a,n;for(a=0;a3M?fv#{(#g|LnqQ}h9dJr=nyAHj^SRo;_puWu=|qMVna|zmE5%YKetw?~x5aEe z_qmzgnR8~|yK-rYukEV~doG-J)C=63yZW5#`{3@h%h!~7>>kBFuWF1;dizdH#y8^N zub2F@x9$4=?!5lmk7Zw^czZ8w*{fTc>=o;^;s2kC=B<@{p{fpbB^S-_smE^nQFK}N z`{MZv;>$Ce9v%%(X!vJ6Mfir{{R59aTJZjSme)JI;=TPwl^+G!d_L9}??x}#;MBb3 z{#`EnIp?42A7P)8=8*s639INe?#(j&+k;bsC##!XGI?8fu%brg-1Uqnmr9py&|AK@ zvi#tsHLFszwwqb}TP`{)b+O*u>H2Z|3;(D#9on{g%Zq=t73KDp=V#v%m^RsbOXTxQ zjbC@&$}9P`Fgxq`|2k)F92_)94V9;o;owt1B4STxC`H(9dy;36fp)s=k@)jqM! zBW>dpn~SY#UoII(FWO|pICrH1n=k*=Baw>29M03YX0DD{>GRfPN#cEJlUyZbaZn}qR7V!`y8~C*KIuDvot4ttAkkjES|H9 z=N3&6f07aDp}J|xA|v0vCF?^hPey2bl31d{bu0N$QdeOVtB8Ei(;4qsHt$eqZ}MwB zp)tYLYvVM|PA->uVu?4n??w8$m0#W_*qga*{jcLs+Lr}28qRWA*&#lqOR4L!$>k^R z8k1%eGX(gwWPULXw4dI+^yaBkE{j~}WglZbHRtF=wF*mN7GCxKqw$l!a<3}de2eSy z38kJ$v9vW4VuJIQdY+ij)ez9~I-Iw~Mw zYOLK-TD|Jwv3))f2kRH#Pl(m`@H^9`)N{gf&Sb|4ip!bYJ~q3akT^YQa}m=o=hx0& z-(7C3l6245-rD5Z7;|FFfi-`)B>DP7Zs&{JNdS*Knm2@A>8SSGnqE+kcUmHeJ{9 z;GIhkZim|o$DeK6*8HOLhFFv7j8xxC&3!Wj?s9%Umi#^OM^c`RJk#Yp?=;VUeOG%^ zY3km6zQ5G($!2~&xSqZDQ^?~La{W&mRbI`|S$X~5^YiO?tdgR3?wRpEet+??zSf6K z**7(6e!p7&-1_*AW4jBUoePdX@VTZkCGY0mC42WoPtw+QlDw*1)i-~2RXV!= z?Jnfhd|&f_=Un6R9N|@`yG-m&FS1-I+EUIx|IE9~#;am(1U6TR##Ps9SBG71U$&-v zRa?2y+rU3M3!}eD@MM1ar{FI$f7a7?zMHw%t#f}YeyQwE++2x-g~r9%3;4ezT(A54 zz;eI;rd5(swq5-{3psXw-RLWF^!yFJzpH;8sECidUwv=Qboa{Z-=EswUa*QYc=-~$ zX}1E8+i&4%j@CGP`_`1Hx8E<|*4Uq299XozteoyCuvOw(=ObbyT$$bp&wlTH*XYV_^00FcX6Hfie28z zm4B;W(bGS5OEKZs{K=Eg9jxQn_AYs6oqGq*!36Oi=?}I%pCMgz*>GO-^78a$o2BRc zmESSn^3B1?8HcAY*pj}V-D3TmhXIdcE^oQtJavtixAT{lqOYP`ehFVP3`yzuyj}jj zMQv#|yExln&CG6P)zdd0J+WJ}Ft(<%XV1);_GL!|JZpK^KA$3a#M?RAtlF)8_pPEc ze_D3Nc+3B@Ol&r>RDbrW^~A>;D_7=5+>o%mr@Zk{MNQC;yV}q1uls%1xctGd^CdI> zm#_Z+Fp>xekioU9N7J8y!_`o74?`_XRs*X8k+oVG*n{?i~L*=|dkD#O1yAlaIb1Jn?o@v3KR2J68U8Q@`%*jz6yvrlEOA@=xmZfU^%C z9atgZE#x^`0--XOjB5sr+(7r0G?LruPMRcf}<<3)nfEx0+k5=I4+0 z(BONO<;S;&6`1~DVY~le(^}ooT&`G;y#JqHtA;!i)%QO5v|POA@!c1T8u?e3?W?Um zyt{U}+6(!bqrAuezdgnI#`^w;n}@&uIAwm_+oIL_|3uw`+qE|*-)ek!PKi}j!lB;W zy2fa(-~H}<1>gR-|0lVEa<-Z<;@vM>wS}7sVww7wB!P(fI#As4xvfK0)pv1me1|vmIGEaiM4=TM* znzqcJAw6NE&RVTQp7T~~ocpBWF8ZFUTy`2*}dX8(g^tQ1G&0HL!@Pe_MJQ;~hKTTn;)R|MP9xu3TaVllmW0vChv>a(BP95$_k5rk~Nu2?O zt=v0!T!qpS_o>$|>Ri5Ey$u{M+ONWSXq{@u! zl@k{1I5BC?1iuf*vP^c#nr~g0{qwjoJITyEJ91^m))Pj(4;s#7h$JyI1S&f7u%%w?Pua^Fx<)KJQ7VH&(AU$e z_@v3TFd<>C8!QI?0pI#tYFloudU7^ODrsG?&$9@Qb;+~TXK_m@$8c@pVBVs=c0+CT znx9K+B`(hS+gIP5YU*q$c(zz5X@Z1vb43@U+KYt^a{|0B|5!1H;s3$EET?V7x|XjH zT@$UaLS#m>(aDW<-xRdOYS?sz92e_}aq#XxuxU@*Gp94xu6-~_l2lv2B(mda)6>qG z4a=S=HntS)(|*g1)o{dp^+27$!W?od9_c# z^FMdqTRf1BKX4^;y_V*H5J> zp`Qn&r({exbg$@%eC@g``W`2y*{zQc=c=23@4Upc>AIF5S1vuM zFMnSl-uKr==9io|r?GqIJrnifk4kYWaK9qWclY;o_29=pZ4ACH@B0+<{@irlgxjx= zEvY~Fb)MP$-=XUR<+5Z#4lleju|;^Y>eo}d_m-w!P`Z5T=gE@aKMqM+iM0u@NLl;f z^zrNK%^C}P%OCm7J-)Bt{O70hcDnv%to>3ek5Ccn+NevP{#XUXI2`@3Eq*nauYr&4jBt>S0x#Wbf}Q#QJ5vnJVf?}DR0kM8K0 zQeN{fX8la7GLEaRowMYlGniy7XTARIpZ58sWSL$@p@XgR^EmTUa#z2u)mzoO>Yt=< z^#uFkd*`fqei`k&u~PW>@x+~fWAZ1hetV&!`_{MPtC^W~O471;zgYgeP`rOv|D5}x zk&)k<<(?fcv2VSbbzkkwqx6#If00|0_voL0Z@t=TyU%SjA~n^{CT@evyCqYvaA1Rf9K9u z{U>nC&)|StoA2|@`8$*C`X9jsDUlI;hvMUO>KH=HZEhXsTwCz(-|O_{*}1;*`xn?N zt#v%&WqE7no!_=E4h8!>@jde;QRJ7&E2#|AqnjLpUZrn3X>4;dbXvkP_AO7N-hJrj ze7*Ff=A|%o7ru7CR^!8G)K2W{_uxGI(D8ct`8oGvz8^K-uKp|9#`E5-X#w}v^{a`8 zmwuL&TJq~Q>w2!-)SJeNV%^`b?|;y^!yomO~7`Th;%0%qNy>A#|8 z{G5OO^1M{JQ}Z2y_Llw6AQH`DwoWJL>ghI_}q5%;RBM_wG@_bKigL NDN`OSGZtZB0002~Y25$- 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 = '{}.{}'

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 Y)8*0W?M<5)Ym7P0?Aa-Md_Ow_065wmyZ`_I delta 56896 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%0A6QRE~hvqkJ$%g=?EbgkaB-?X@- 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 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 @@ -

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¬dz*Fsr_W0^ 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 F0{{eq9LfLy delta 170763 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