From a77fd4892e8ab1c0da8c3e2e5aea68ec9d0dab35 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 26 Feb 2020 19:24:43 +0100 Subject: [PATCH 01/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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