From a77fd4892e8ab1c0da8c3e2e5aea68ec9d0dab35 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 26 Feb 2020 19:24:43 +0100 Subject: [PATCH 01/15] Add missing translations for light actions (#32216) --- homeassistant/components/light/strings.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/light/strings.json b/homeassistant/components/light/strings.json index 77b842ba078..922a4957afd 100644 --- a/homeassistant/components/light/strings.json +++ b/homeassistant/components/light/strings.json @@ -1,6 +1,8 @@ { "device_automation": { "action_type": { + "brightness_decrease": "Decrease {entity_name} brightness", + "brightness_increase": "Increase {entity_name} brightness", "toggle": "Toggle {entity_name}", "turn_on": "Turn on {entity_name}", "turn_off": "Turn off {entity_name}" From a5d334bbf7b708b990a314509da4c667c6462e8c Mon Sep 17 00:00:00 2001 From: Jens Nistler Date: Thu, 27 Feb 2020 20:50:34 +0100 Subject: [PATCH 02/15] Mark clients away if they have never been seen. (#32222) --- .../components/unifi/device_tracker.py | 5 +++++ tests/components/unifi/test_device_tracker.py | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/unifi/device_tracker.py b/homeassistant/components/unifi/device_tracker.py index 5dd5f0c83ae..52370fb0e3d 100644 --- a/homeassistant/components/unifi/device_tracker.py +++ b/homeassistant/components/unifi/device_tracker.py @@ -200,6 +200,11 @@ class UniFiClientTracker(UniFiClient, ScannerEntity): else: self.wired_bug = None + + # A client that has never been seen cannot be connected. + if self.client.last_seen is None: + return False + since_last_seen = dt_util.utcnow() - dt_util.utc_from_timestamp( float(self.client.last_seen) ) diff --git a/tests/components/unifi/test_device_tracker.py b/tests/components/unifi/test_device_tracker.py index 608e72b483a..cbef7c31922 100644 --- a/tests/components/unifi/test_device_tracker.py +++ b/tests/components/unifi/test_device_tracker.py @@ -54,6 +54,14 @@ CLIENT_4 = { "last_seen": 1562600145, "mac": "00:00:00:00:00:04", } +CLIENT_5 = { + "essid": "ssid", + "hostname": "client_5", + "ip": "10.0.0.5", + "is_wired": True, + "last_seen": None, + "mac": "00:00:00:00:00:05", +} DEVICE_1 = { "board_rev": 3, @@ -111,11 +119,11 @@ async def test_tracked_devices(hass): controller = await setup_unifi_integration( hass, options={CONF_SSID_FILTER: ["ssid"]}, - clients_response=[CLIENT_1, CLIENT_2, CLIENT_3, client_4_copy], + clients_response=[CLIENT_1, CLIENT_2, CLIENT_3, CLIENT_5, client_4_copy], devices_response=[DEVICE_1, DEVICE_2], known_wireless_clients=(CLIENT_4["mac"],), ) - assert len(hass.states.async_all()) == 6 + assert len(hass.states.async_all()) == 7 client_1 = hass.states.get("device_tracker.client_1") assert client_1 is not None @@ -134,6 +142,11 @@ async def test_tracked_devices(hass): assert client_4 is not None assert client_4.state == "not_home" + # A client that has never been seen should be marked away. + client_5 = hass.states.get("device_tracker.client_5") + assert client_5 is not None + assert client_5.state == "not_home" + device_1 = hass.states.get("device_tracker.device_1") assert device_1 is not None assert device_1.state == "not_home" From 6d0a46539087b7387f19115724b09ae81f838662 Mon Sep 17 00:00:00 2001 From: dupondje Date: Thu, 27 Feb 2020 02:02:42 +0100 Subject: [PATCH 03/15] Fix DSMR 5 (#32233) DSMR 5 was broken because some wrong if. if dsmr_version in ("5B"): -> this checks dsmr_version against 5 and B. Not if its 5B. --- homeassistant/components/dsmr/sensor.py | 4 +-- tests/components/dsmr/test_sensor.py | 44 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/dsmr/sensor.py b/homeassistant/components/dsmr/sensor.py index 54c8e3e29b2..009b86e1bb8 100644 --- a/homeassistant/components/dsmr/sensor.py +++ b/homeassistant/components/dsmr/sensor.py @@ -91,7 +91,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= # Protocol version specific obis if dsmr_version in ("4", "5"): gas_obis = obis_ref.HOURLY_GAS_METER_READING - elif dsmr_version in ("5B"): + elif dsmr_version in ("5B",): gas_obis = obis_ref.BELGIUM_HOURLY_GAS_METER_READING else: gas_obis = obis_ref.GAS_METER_READING @@ -238,7 +238,7 @@ class DSMREntity(Entity): """Convert 2/1 to normal/low depending on DSMR version.""" # DSMR V5B: Note: In Belgium values are swapped: # Rate code 2 is used for low rate and rate code 1 is used for normal rate. - if dsmr_version in ("5B"): + if dsmr_version in ("5B",): if value == "0001": value = "0002" elif value == "0002": diff --git a/tests/components/dsmr/test_sensor.py b/tests/components/dsmr/test_sensor.py index c881f4b9168..30138901c14 100644 --- a/tests/components/dsmr/test_sensor.py +++ b/tests/components/dsmr/test_sensor.py @@ -187,6 +187,50 @@ async def test_v4_meter(hass, mock_connection_factory): assert gas_consumption.attributes.get("unit_of_measurement") == "m3" +async def test_v5_meter(hass, mock_connection_factory): + """Test if v5 meter is correctly parsed.""" + (connection_factory, transport, protocol) = mock_connection_factory + + from dsmr_parser.obis_references import ( + HOURLY_GAS_METER_READING, + ELECTRICITY_ACTIVE_TARIFF, + ) + from dsmr_parser.objects import CosemObject, MBusObject + + config = {"platform": "dsmr", "dsmr_version": "5"} + + telegram = { + HOURLY_GAS_METER_READING: MBusObject( + [ + {"value": datetime.datetime.fromtimestamp(1551642213)}, + {"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS}, + ] + ), + ELECTRICITY_ACTIVE_TARIFF: CosemObject([{"value": "0001", "unit": ""}]), + } + + with assert_setup_component(1): + await async_setup_component(hass, "sensor", {"sensor": config}) + + telegram_callback = connection_factory.call_args_list[0][0][2] + + # simulate a telegram pushed from the smartmeter and parsed by dsmr_parser + telegram_callback(telegram) + + # after receiving telegram entities need to have the chance to update + await asyncio.sleep(0) + + # tariff should be translated in human readable and have no unit + power_tariff = hass.states.get("sensor.power_tariff") + assert power_tariff.state == "low" + assert power_tariff.attributes.get("unit_of_measurement") == "" + + # check if gas consumption is parsed correctly + gas_consumption = hass.states.get("sensor.gas_consumption") + assert gas_consumption.state == "745.695" + assert gas_consumption.attributes.get("unit_of_measurement") == VOLUME_CUBIC_METERS + + async def test_belgian_meter(hass, mock_connection_factory): """Test if Belgian meter is correctly parsed.""" (connection_factory, transport, protocol) = mock_connection_factory From 58b32bbeff65008ad7f595be67bc47f894b235f0 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Wed, 26 Feb 2020 19:52:07 -0700 Subject: [PATCH 04/15] Bump simplisafe-python to 9.0.0 (#32215) --- homeassistant/components/simplisafe/__init__.py | 8 ++------ homeassistant/components/simplisafe/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/simplisafe/__init__.py b/homeassistant/components/simplisafe/__init__.py index 09004189820..add37cb0f1e 100644 --- a/homeassistant/components/simplisafe/__init__.py +++ b/homeassistant/components/simplisafe/__init__.py @@ -154,6 +154,7 @@ CONFIG_SCHEMA = vol.Schema( @callback def _async_save_refresh_token(hass, config_entry, token): + """Save a refresh token to the config entry.""" hass.config_entries.async_update_entry( config_entry, data={**config_entry.data, CONF_TOKEN: token} ) @@ -547,12 +548,7 @@ class SimpliSafe: _LOGGER.error("Unknown error while updating: %s", result) return - if self._api.refresh_token_dirty: - # Reconnect the websocket: - await self._api.websocket.async_disconnect() - await self._api.websocket.async_connect() - - # Save the new refresh token: + if self._api.refresh_token != self._config_entry.data[CONF_TOKEN]: _async_save_refresh_token( self._hass, self._config_entry, self._api.refresh_token ) diff --git a/homeassistant/components/simplisafe/manifest.json b/homeassistant/components/simplisafe/manifest.json index e44f39265cb..ad753dfd8b0 100644 --- a/homeassistant/components/simplisafe/manifest.json +++ b/homeassistant/components/simplisafe/manifest.json @@ -3,7 +3,7 @@ "name": "SimpliSafe", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/simplisafe", - "requirements": ["simplisafe-python==8.1.1"], + "requirements": ["simplisafe-python==9.0.0"], "dependencies": [], "codeowners": ["@bachya"] } diff --git a/requirements_all.txt b/requirements_all.txt index a340f99d7c6..c1f04f9b0ff 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1827,7 +1827,7 @@ simplehound==0.3 simplepush==1.1.4 # homeassistant.components.simplisafe -simplisafe-python==8.1.1 +simplisafe-python==9.0.0 # homeassistant.components.sisyphus sisyphus-control==2.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index be073a4b929..e1b5782e99f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -626,7 +626,7 @@ sentry-sdk==0.13.5 simplehound==0.3 # homeassistant.components.simplisafe -simplisafe-python==8.1.1 +simplisafe-python==9.0.0 # homeassistant.components.sleepiq sleepyq==0.7 From f43b26f250e14c9a79c63a8563a309aae7364e05 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Thu, 27 Feb 2020 12:18:26 -0700 Subject: [PATCH 05/15] Bump simplisafe-python to 9.0.2 (#32273) --- homeassistant/components/simplisafe/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/simplisafe/manifest.json b/homeassistant/components/simplisafe/manifest.json index ad753dfd8b0..b5f89a65fea 100644 --- a/homeassistant/components/simplisafe/manifest.json +++ b/homeassistant/components/simplisafe/manifest.json @@ -3,7 +3,7 @@ "name": "SimpliSafe", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/simplisafe", - "requirements": ["simplisafe-python==9.0.0"], + "requirements": ["simplisafe-python==9.0.2"], "dependencies": [], "codeowners": ["@bachya"] } diff --git a/requirements_all.txt b/requirements_all.txt index c1f04f9b0ff..22a451b08d1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1827,7 +1827,7 @@ simplehound==0.3 simplepush==1.1.4 # homeassistant.components.simplisafe -simplisafe-python==9.0.0 +simplisafe-python==9.0.2 # homeassistant.components.sisyphus sisyphus-control==2.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e1b5782e99f..ff7748259a3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -626,7 +626,7 @@ sentry-sdk==0.13.5 simplehound==0.3 # homeassistant.components.simplisafe -simplisafe-python==9.0.0 +simplisafe-python==9.0.2 # homeassistant.components.sleepiq sleepyq==0.7 From a5d9e89d0876016bf7bf36329cc4ae1e5ff3d8dc Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Thu, 27 Feb 2020 20:48:01 +0100 Subject: [PATCH 06/15] deCONZ - Race condition on slower systems (#32274) When battery sensors gets created before other platforms loading deconz sensors gets created first the other platform would not create entities related to those battery sensors --- homeassistant/components/deconz/binary_sensor.py | 1 - homeassistant/components/deconz/climate.py | 1 - homeassistant/components/deconz/light.py | 2 +- homeassistant/components/deconz/sensor.py | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/homeassistant/components/deconz/binary_sensor.py b/homeassistant/components/deconz/binary_sensor.py index 2514a49f23c..6a528a66ba6 100644 --- a/homeassistant/components/deconz/binary_sensor.py +++ b/homeassistant/components/deconz/binary_sensor.py @@ -37,7 +37,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities): gateway.option_allow_clip_sensor or not sensor.type.startswith("CLIP") ) - and sensor.deconz_id not in gateway.deconz_ids.values() ): entities.append(DeconzBinarySensor(sensor, gateway)) diff --git a/homeassistant/components/deconz/climate.py b/homeassistant/components/deconz/climate.py index 34cc0e0b832..7b0f44807ec 100644 --- a/homeassistant/components/deconz/climate.py +++ b/homeassistant/components/deconz/climate.py @@ -44,7 +44,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities): gateway.option_allow_clip_sensor or not sensor.type.startswith("CLIP") ) - and sensor.deconz_id not in gateway.deconz_ids.values() ): entities.append(DeconzThermostat(sensor, gateway)) diff --git a/homeassistant/components/deconz/light.py b/homeassistant/components/deconz/light.py index f62f9315c49..e836f1e4490 100644 --- a/homeassistant/components/deconz/light.py +++ b/homeassistant/components/deconz/light.py @@ -67,7 +67,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entities = [] for group in groups: - if group.lights and group.deconz_id not in gateway.deconz_ids.values(): + if group.lights: entities.append(DeconzGroup(group, gateway)) async_add_entities(entities, True) diff --git a/homeassistant/components/deconz/sensor.py b/homeassistant/components/deconz/sensor.py index 6b88c414243..c32b26f299d 100644 --- a/homeassistant/components/deconz/sensor.py +++ b/homeassistant/components/deconz/sensor.py @@ -68,7 +68,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities): gateway.option_allow_clip_sensor or not sensor.type.startswith("CLIP") ) - and sensor.deconz_id not in gateway.deconz_ids.values() ): entities.append(DeconzSensor(sensor, gateway)) From c0394232f3b73b377ac550a5ee0585f3088f5fbb Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Feb 2020 12:53:36 -0800 Subject: [PATCH 07/15] Catch more Hue errors (#32275) --- homeassistant/components/hue/bridge.py | 13 ++++++++++--- homeassistant/components/hue/light.py | 7 ++++++- homeassistant/components/hue/sensor_base.py | 3 ++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/hue/bridge.py b/homeassistant/components/hue/bridge.py index 2c164e5769a..37089e54b00 100644 --- a/homeassistant/components/hue/bridge.py +++ b/homeassistant/components/hue/bridge.py @@ -1,6 +1,7 @@ """Code to handle a Hue bridge.""" import asyncio from functools import partial +import logging from aiohttp import client_exceptions import aiohue @@ -24,7 +25,8 @@ SCENE_SCHEMA = vol.Schema( {vol.Required(ATTR_GROUP_NAME): cv.string, vol.Required(ATTR_SCENE_NAME): cv.string} ) # How long should we sleep if the hub is busy -HUB_BUSY_SLEEP = 0.01 +HUB_BUSY_SLEEP = 0.5 +_LOGGER = logging.getLogger(__name__) class HueBridge: @@ -123,9 +125,14 @@ class HueBridge: except ( client_exceptions.ClientOSError, client_exceptions.ClientResponseError, + client_exceptions.ServerDisconnectedError, ) as err: - if tries == 3 or ( - # We only retry if it's a server error. So raise on all 4XX errors. + if tries == 3: + _LOGGER.error("Request failed %s times, giving up.", tries) + raise + + # We only retry if it's a server error. So raise on all 4XX errors. + if ( isinstance(err, client_exceptions.ClientResponseError) and err.status < 500 ): diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index 1678dbbfc62..253c0a2069c 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -5,6 +5,7 @@ from functools import partial import logging import random +from aiohttp import client_exceptions import aiohue import async_timeout @@ -172,7 +173,11 @@ async def async_safe_fetch(bridge, fetch_method): except aiohue.Unauthorized: await bridge.handle_unauthorized_error() raise UpdateFailed - except (asyncio.TimeoutError, aiohue.AiohueException): + except ( + asyncio.TimeoutError, + aiohue.AiohueException, + client_exceptions.ClientError, + ): raise UpdateFailed diff --git a/homeassistant/components/hue/sensor_base.py b/homeassistant/components/hue/sensor_base.py index 0bc7cd53536..ed27cff8eab 100644 --- a/homeassistant/components/hue/sensor_base.py +++ b/homeassistant/components/hue/sensor_base.py @@ -3,6 +3,7 @@ import asyncio from datetime import timedelta import logging +from aiohttp import client_exceptions from aiohue import AiohueException, Unauthorized from aiohue.sensors import TYPE_ZLL_PRESENCE import async_timeout @@ -60,7 +61,7 @@ class SensorManager: except Unauthorized: await self.bridge.handle_unauthorized_error() raise UpdateFailed - except (asyncio.TimeoutError, AiohueException): + except (asyncio.TimeoutError, AiohueException, client_exceptions.ClientError): raise UpdateFailed async def async_register_component(self, binary, async_add_entities): From cab60bcd0c39885c724a2d7586f6a54362c0d17a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Feb 2020 14:03:07 -0800 Subject: [PATCH 08/15] Bumped version to 0.106.1 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index ff8e6bf8a9e..f453e211897 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 106 -PATCH_VERSION = "0" +PATCH_VERSION = "1" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 7, 0) From 61476f4f2c4bce1599cfc67a94f53ed4df32e093 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Feb 2020 14:41:35 -0800 Subject: [PATCH 09/15] Fix dsmr test --- tests/components/dsmr/test_sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/dsmr/test_sensor.py b/tests/components/dsmr/test_sensor.py index 30138901c14..426ba552136 100644 --- a/tests/components/dsmr/test_sensor.py +++ b/tests/components/dsmr/test_sensor.py @@ -203,7 +203,7 @@ async def test_v5_meter(hass, mock_connection_factory): HOURLY_GAS_METER_READING: MBusObject( [ {"value": datetime.datetime.fromtimestamp(1551642213)}, - {"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS}, + {"value": Decimal(745.695), "unit": "m³"}, ] ), ELECTRICITY_ACTIVE_TARIFF: CosemObject([{"value": "0001", "unit": ""}]), @@ -228,7 +228,7 @@ async def test_v5_meter(hass, mock_connection_factory): # check if gas consumption is parsed correctly gas_consumption = hass.states.get("sensor.gas_consumption") assert gas_consumption.state == "745.695" - assert gas_consumption.attributes.get("unit_of_measurement") == VOLUME_CUBIC_METERS + assert gas_consumption.attributes.get("unit_of_measurement") == "m³" async def test_belgian_meter(hass, mock_connection_factory): From b8fbe758d8768d27db1712579659b1a8a65c7586 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Thu, 27 Feb 2020 22:44:02 +0000 Subject: [PATCH 10/15] Bump pyipma dependency (fixes bug in 0.106) (#32286) * Bump version * Bump PyIPMA version --- homeassistant/components/ipma/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ipma/manifest.json b/homeassistant/components/ipma/manifest.json index 02d4e459f72..1457ac24195 100644 --- a/homeassistant/components/ipma/manifest.json +++ b/homeassistant/components/ipma/manifest.json @@ -3,7 +3,7 @@ "name": "Instituto Português do Mar e Atmosfera (IPMA)", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/ipma", - "requirements": ["pyipma==2.0.3"], + "requirements": ["pyipma==2.0.4"], "dependencies": [], "codeowners": ["@dgomes", "@abmantis"] } diff --git a/requirements_all.txt b/requirements_all.txt index 22a451b08d1..252b6d9c6a1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1305,7 +1305,7 @@ pyicloud==0.9.2 pyintesishome==1.6 # homeassistant.components.ipma -pyipma==2.0.3 +pyipma==2.0.4 # homeassistant.components.iqvia pyiqvia==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ff7748259a3..3b0480ffe64 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -477,7 +477,7 @@ pyhomematic==0.1.64 pyicloud==0.9.2 # homeassistant.components.ipma -pyipma==2.0.3 +pyipma==2.0.4 # homeassistant.components.iqvia pyiqvia==0.2.1 From 430fa24acd59f21164c4e6429bbce164e07a9df2 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 28 Feb 2020 16:56:39 +0100 Subject: [PATCH 11/15] Updated frontend to 20200220.5 (#32312) --- homeassistant/components/frontend/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index b9575b7f21a..b957ef13895 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -3,7 +3,7 @@ "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", "requirements": [ - "home-assistant-frontend==20200220.4" + "home-assistant-frontend==20200220.5" ], "dependencies": [ "api", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 7d6f445c1e4..d8450d873b7 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -11,7 +11,7 @@ cryptography==2.8 defusedxml==0.6.0 distro==1.4.0 hass-nabucasa==0.31 -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 importlib-metadata==1.5.0 jinja2>=2.10.3 netdisco==2.6.0 diff --git a/requirements_all.txt b/requirements_all.txt index 252b6d9c6a1..d3f81477a80 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -683,7 +683,7 @@ hole==0.5.0 holidays==0.10.1 # homeassistant.components.frontend -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 # homeassistant.components.zwave homeassistant-pyozw==0.1.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3b0480ffe64..bf9106725b5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -254,7 +254,7 @@ hole==0.5.0 holidays==0.10.1 # homeassistant.components.frontend -home-assistant-frontend==20200220.4 +home-assistant-frontend==20200220.5 # homeassistant.components.zwave homeassistant-pyozw==0.1.8 From c43b7d10d88b2b6d141fdf8380e0e7972b9543fd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 28 Feb 2020 11:12:16 -0800 Subject: [PATCH 12/15] revent saving/deleting Lovelace config in safe mode (#32319) --- homeassistant/components/lovelace/__init__.py | 6 ++++++ tests/components/lovelace/test_init.py | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/homeassistant/components/lovelace/__init__.py b/homeassistant/components/lovelace/__init__.py index fc8cb67894b..b986c61ea36 100644 --- a/homeassistant/components/lovelace/__init__.py +++ b/homeassistant/components/lovelace/__init__.py @@ -104,6 +104,9 @@ class LovelaceStorage: async def async_save(self, config): """Save config.""" + if self._hass.config.safe_mode: + raise HomeAssistantError("Deleting not supported in safe mode") + if self._data is None: await self._load() self._data["config"] = config @@ -112,6 +115,9 @@ class LovelaceStorage: async def async_delete(self): """Delete config.""" + if self._hass.config.safe_mode: + raise HomeAssistantError("Deleting not supported in safe mode") + await self.async_save(None) async def _load(self): diff --git a/tests/components/lovelace/test_init.py b/tests/components/lovelace/test_init.py index 82e7b3bc2ac..c79e447f5af 100644 --- a/tests/components/lovelace/test_init.py +++ b/tests/components/lovelace/test_init.py @@ -45,6 +45,16 @@ async def test_lovelace_from_storage(hass, hass_ws_client, hass_storage): assert not response["success"] assert response["error"]["code"] == "config_not_found" + await client.send_json( + {"id": 9, "type": "lovelace/config/save", "config": {"yo": "hello"}} + ) + response = await client.receive_json() + assert not response["success"] + + await client.send_json({"id": 10, "type": "lovelace/config/delete"}) + response = await client.receive_json() + assert not response["success"] + async def test_lovelace_from_storage_save_before_load( hass, hass_ws_client, hass_storage From 6ea20090a485ac992292c82ea568b9fcec153983 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 28 Feb 2020 19:28:03 +0100 Subject: [PATCH 13/15] =?UTF-8?q?UniFi=20-=20Temporary=20workaround=20to?= =?UTF-8?q?=20get=20device=20tracker=20to=20mark=20cli=E2=80=A6=20(#32321)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homeassistant/components/unifi/device_tracker.py | 2 +- homeassistant/components/unifi/unifi_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/unifi/device_tracker.py b/homeassistant/components/unifi/device_tracker.py index 52370fb0e3d..b398dad488b 100644 --- a/homeassistant/components/unifi/device_tracker.py +++ b/homeassistant/components/unifi/device_tracker.py @@ -338,4 +338,4 @@ class UniFiDeviceTracker(ScannerEntity): @property def should_poll(self): """No polling needed.""" - return False + return True diff --git a/homeassistant/components/unifi/unifi_client.py b/homeassistant/components/unifi/unifi_client.py index 2e18f55a57b..f9e77d47c0e 100644 --- a/homeassistant/components/unifi/unifi_client.py +++ b/homeassistant/components/unifi/unifi_client.py @@ -62,4 +62,4 @@ class UniFiClient(Entity): @property def should_poll(self) -> bool: """No polling needed.""" - return False + return True From e62ba49979aef5230c9477ecf6629a4a1f3b0125 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 28 Feb 2020 11:38:53 -0800 Subject: [PATCH 14/15] Bumped version to 0.106.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f453e211897..11b3c87db27 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 106 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 7, 0) From ca81c6e684d54f0c173e06911082e70d753ea487 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 28 Feb 2020 09:41:41 -1000 Subject: [PATCH 15/15] =?UTF-8?q?Ensure=20rest=20sensors=20are=20marked=20?= =?UTF-8?q?unavailable=20when=20http=20requests=E2=80=A6=20(#32309)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homeassistant/components/rest/sensor.py | 22 ++++++++++--------- tests/components/rest/test_sensor.py | 29 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/rest/sensor.py b/homeassistant/components/rest/sensor.py index 70424325241..7c8cfb9d3d0 100644 --- a/homeassistant/components/rest/sensor.py +++ b/homeassistant/components/rest/sensor.py @@ -202,17 +202,19 @@ class RestSensor(Entity): self.rest.update() value = self.rest.data _LOGGER.debug("Data fetched from resource: %s", value) - content_type = self.rest.headers.get("content-type") + if self.rest.headers is not None: + # If the http request failed, headers will be None + content_type = self.rest.headers.get("content-type") - if content_type and content_type.startswith("text/xml"): - try: - value = json.dumps(xmltodict.parse(value)) - _LOGGER.debug("JSON converted from XML: %s", value) - except ExpatError: - _LOGGER.warning( - "REST xml result could not be parsed and converted to JSON." - ) - _LOGGER.debug("Erroneous XML: %s", value) + if content_type and content_type.startswith("text/xml"): + try: + value = json.dumps(xmltodict.parse(value)) + _LOGGER.debug("JSON converted from XML: %s", value) + except ExpatError: + _LOGGER.warning( + "REST xml result could not be parsed and converted to JSON." + ) + _LOGGER.debug("Erroneous XML: %s", value) if self._json_attrs: self._attributes = {} diff --git a/tests/components/rest/test_sensor.py b/tests/components/rest/test_sensor.py index 30eeae9a8e3..5018418f493 100644 --- a/tests/components/rest/test_sensor.py +++ b/tests/components/rest/test_sensor.py @@ -589,6 +589,35 @@ class TestRestSensor(unittest.TestCase): assert mock_logger.warning.called assert mock_logger.debug.called + @patch("homeassistant.components.rest.sensor._LOGGER") + def test_update_with_failed_get(self, mock_logger): + """Test attributes get extracted from a XML result with bad xml.""" + value_template = template("{{ value_json.toplevel.master_value }}") + value_template.hass = self.hass + + self.rest.update = Mock( + "rest.RestData.update", side_effect=self.update_side_effect(None, None), + ) + self.sensor = rest.RestSensor( + self.hass, + self.rest, + self.name, + self.unit_of_measurement, + self.device_class, + value_template, + ["key"], + self.force_update, + self.resource_template, + self.json_attrs_path, + ) + + self.sensor.update() + assert {} == self.sensor.device_state_attributes + assert mock_logger.warning.called + assert mock_logger.debug.called + assert self.sensor.state is None + assert self.sensor.available is False + class TestRestData(unittest.TestCase): """Tests for RestData."""