From 0f3b73e75fc5d4afd6787abaca63b47d0a06df98 Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Fri, 4 Jun 2021 18:03:13 -0300 Subject: [PATCH 01/17] Use a single job to ping all devices in the Broadlink integration (#51466) --- homeassistant/components/broadlink/heartbeat.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/broadlink/heartbeat.py b/homeassistant/components/broadlink/heartbeat.py index 282df3ae6a8..b4deffa5b81 100644 --- a/homeassistant/components/broadlink/heartbeat.py +++ b/homeassistant/components/broadlink/heartbeat.py @@ -44,11 +44,15 @@ class BroadlinkHeartbeat: """Send packets to feed watchdog timers.""" hass = self._hass config_entries = hass.config_entries.async_entries(DOMAIN) + hosts = {entry.data[CONF_HOST] for entry in config_entries} + await hass.async_add_executor_job(self.heartbeat, hosts) - for entry in config_entries: - host = entry.data[CONF_HOST] + @staticmethod + def heartbeat(hosts): + """Send packets to feed watchdog timers.""" + for host in hosts: try: - await hass.async_add_executor_job(blk.ping, host) + blk.ping(host) except OSError as err: _LOGGER.debug("Failed to send heartbeat to %s: %s", host, err) else: From 703b088f861581bd3013005f975964e6565c454d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 7 Jun 2021 08:21:10 -1000 Subject: [PATCH 02/17] Fix loop in tod binary sensor (#51491) Co-authored-by: Paulus Schoutsen --- homeassistant/components/tod/binary_sensor.py | 22 +- tests/components/tod/test_binary_sensor.py | 219 +++++++++++++++++- 2 files changed, 237 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/tod/binary_sensor.py b/homeassistant/components/tod/binary_sensor.py index 4fd9a3b8bf9..8264468e2e7 100644 --- a/homeassistant/components/tod/binary_sensor.py +++ b/homeassistant/components/tod/binary_sensor.py @@ -156,6 +156,26 @@ class TodSensor(BinarySensorEntity): self._time_after += self._after_offset self._time_before += self._before_offset + def _turn_to_next_day(self): + """Turn to to the next day.""" + if is_sun_event(self._after): + self._time_after = get_astral_event_next( + self.hass, self._after, self._time_after - self._after_offset + ) + self._time_after += self._after_offset + else: + # Offset is already there + self._time_after += timedelta(days=1) + + if is_sun_event(self._before): + self._time_before = get_astral_event_next( + self.hass, self._before, self._time_before - self._before_offset + ) + self._time_before += self._before_offset + else: + # Offset is already there + self._time_before += timedelta(days=1) + async def async_added_to_hass(self): """Call when entity about to be added to Home Assistant.""" self._calculate_boudary_time() @@ -182,7 +202,7 @@ class TodSensor(BinarySensorEntity): if now < self._time_before: self._next_update = self._time_before return - self._calculate_boudary_time() + self._turn_to_next_day() self._next_update = self._time_after @callback diff --git a/tests/components/tod/test_binary_sensor.py b/tests/components/tod/test_binary_sensor.py index 8b63082c36c..ef8088d6aab 100644 --- a/tests/components/tod/test_binary_sensor.py +++ b/tests/components/tod/test_binary_sensor.py @@ -12,6 +12,8 @@ import homeassistant.util.dt as dt_util from tests.common import assert_setup_component +ORIG_TIMEZONE = dt_util.DEFAULT_TIME_ZONE + @pytest.fixture(autouse=True) def mock_legacy_time(legacy_patchable_time): @@ -26,6 +28,13 @@ def setup_fixture(hass): hass.config.longitude = 18.98583 +@pytest.fixture(autouse=True) +def restore_timezone(hass): + """Make sure we change timezone.""" + yield + dt_util.set_default_time_zone(ORIG_TIMEZONE) + + async def test_setup(hass): """Test the setup.""" config = { @@ -863,6 +872,7 @@ async def test_sun_offset(hass): async def test_dst(hass): """Test sun event with offset.""" hass.config.time_zone = "CET" + dt_util.set_default_time_zone(dt_util.get_time_zone("CET")) test_time = datetime(2019, 3, 30, 3, 0, 0, tzinfo=dt_util.UTC) config = { "binary_sensor": [ @@ -882,7 +892,210 @@ async def test_dst(hass): await hass.async_block_till_done() state = hass.states.get(entity_id) - assert state.attributes["after"] == "2019-03-30T03:30:00+01:00" - assert state.attributes["before"] == "2019-03-30T03:40:00+01:00" - assert state.attributes["next_update"] == "2019-03-30T03:30:00+01:00" + assert state.attributes["after"] == "2019-03-31T03:30:00+02:00" + assert state.attributes["before"] == "2019-03-31T03:40:00+02:00" + assert state.attributes["next_update"] == "2019-03-31T03:30:00+02:00" assert state.state == STATE_OFF + + +async def test_simple_before_after_does_not_loop_utc_not_in_range(hass): + """Test simple before after.""" + hass.config.time_zone = "UTC" + dt_util.set_default_time_zone(dt_util.UTC) + test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Night", + "before": "06:00", + "after": "22:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.night") + assert state.state == STATE_OFF + assert state.attributes["after"] == "2019-01-10T22:00:00+00:00" + assert state.attributes["before"] == "2019-01-11T06:00:00+00:00" + assert state.attributes["next_update"] == "2019-01-10T22:00:00+00:00" + + +async def test_simple_before_after_does_not_loop_utc_in_range(hass): + """Test simple before after.""" + hass.config.time_zone = "UTC" + dt_util.set_default_time_zone(dt_util.UTC) + test_time = datetime(2019, 1, 10, 22, 43, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Night", + "before": "06:00", + "after": "22:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.night") + assert state.state == STATE_ON + assert state.attributes["after"] == "2019-01-10T22:00:00+00:00" + assert state.attributes["before"] == "2019-01-11T06:00:00+00:00" + assert state.attributes["next_update"] == "2019-01-11T06:00:00+00:00" + + +async def test_simple_before_after_does_not_loop_utc_fire_at_before(hass): + """Test simple before after.""" + hass.config.time_zone = "UTC" + dt_util.set_default_time_zone(dt_util.UTC) + test_time = datetime(2019, 1, 11, 6, 0, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Night", + "before": "06:00", + "after": "22:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.night") + assert state.state == STATE_OFF + assert state.attributes["after"] == "2019-01-11T22:00:00+00:00" + assert state.attributes["before"] == "2019-01-12T06:00:00+00:00" + assert state.attributes["next_update"] == "2019-01-11T22:00:00+00:00" + + +async def test_simple_before_after_does_not_loop_utc_fire_at_after(hass): + """Test simple before after.""" + hass.config.time_zone = "UTC" + dt_util.set_default_time_zone(dt_util.UTC) + test_time = datetime(2019, 1, 10, 22, 0, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Night", + "before": "06:00", + "after": "22:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.night") + assert state.state == STATE_ON + assert state.attributes["after"] == "2019-01-10T22:00:00+00:00" + assert state.attributes["before"] == "2019-01-11T06:00:00+00:00" + assert state.attributes["next_update"] == "2019-01-11T06:00:00+00:00" + + +async def test_simple_before_after_does_not_loop_utc_both_before_now(hass): + """Test simple before after.""" + hass.config.time_zone = "UTC" + dt_util.set_default_time_zone(dt_util.UTC) + test_time = datetime(2019, 1, 10, 22, 0, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Morning", + "before": "08:00", + "after": "00:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.morning") + assert state.state == STATE_OFF + assert state.attributes["after"] == "2019-01-11T00:00:00+00:00" + assert state.attributes["before"] == "2019-01-11T08:00:00+00:00" + assert state.attributes["next_update"] == "2019-01-11T00:00:00+00:00" + + +async def test_simple_before_after_does_not_loop_berlin_not_in_range(hass): + """Test simple before after.""" + hass.config.time_zone = "Europe/Berlin" + dt_util.set_default_time_zone(dt_util.get_time_zone("Europe/Berlin")) + test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Dark", + "before": "06:00", + "after": "00:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.dark") + assert state.state == STATE_OFF + assert state.attributes["after"] == "2019-01-11T00:00:00+01:00" + assert state.attributes["before"] == "2019-01-11T06:00:00+01:00" + assert state.attributes["next_update"] == "2019-01-11T00:00:00+01:00" + + +async def test_simple_before_after_does_not_loop_berlin_in_range(hass): + """Test simple before after.""" + hass.config.time_zone = "Europe/Berlin" + dt_util.set_default_time_zone(dt_util.get_time_zone("Europe/Berlin")) + test_time = datetime(2019, 1, 10, 23, 43, 0, tzinfo=dt_util.UTC) + config = { + "binary_sensor": [ + { + "platform": "tod", + "name": "Dark", + "before": "06:00", + "after": "00:00", + } + ] + } + with patch( + "homeassistant.components.tod.binary_sensor.dt_util.utcnow", + return_value=test_time, + ): + await async_setup_component(hass, "binary_sensor", config) + await hass.async_block_till_done() + + state = hass.states.get("binary_sensor.dark") + assert state.state == STATE_ON + assert state.attributes["after"] == "2019-01-11T00:00:00+01:00" + assert state.attributes["before"] == "2019-01-11T06:00:00+01:00" + assert state.attributes["next_update"] == "2019-01-11T06:00:00+01:00" From 96ade688d5b62fdf709a647aedf24245f193bb5a Mon Sep 17 00:00:00 2001 From: Aidan Timson Date: Mon, 7 Jun 2021 19:21:24 +0100 Subject: [PATCH 03/17] AsusWRT fix keyerror when firmver is missing from info (#51499) Co-authored-by: Franck Nijhof Co-authored-by: Paulus Schoutsen --- homeassistant/components/asuswrt/router.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/asuswrt/router.py b/homeassistant/components/asuswrt/router.py index 0912869abb7..134cf960aae 100644 --- a/homeassistant/components/asuswrt/router.py +++ b/homeassistant/components/asuswrt/router.py @@ -228,10 +228,10 @@ class AsusWrtRouter: # System model = await _get_nvram_info(self._api, "MODEL") - if model: + if model and "model" in model: self._model = model["model"] firmware = await _get_nvram_info(self._api, "FIRMWARE") - if firmware: + if firmware and "firmver" in firmware and "buildno" in firmware: self._sw_v = f"{firmware['firmver']} (build {firmware['buildno']})" # Load tracked entities from registry From 89db8d45199cdbf7ce23f22939ff6e44433af88b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 5 Jun 2021 00:13:12 -1000 Subject: [PATCH 04/17] Handle missing options in foreign_key for MSSQL (#51503) --- homeassistant/components/recorder/migration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index 8e6c4861739..02c74635f03 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -280,10 +280,10 @@ def _update_states_table_with_foreign_key_options(connection, engine): for foreign_key in inspector.get_foreign_keys(TABLE_STATES): if foreign_key["name"] and ( # MySQL/MariaDB will have empty options - not foreign_key["options"] + not foreign_key.get("options") or # Postgres will have ondelete set to None - foreign_key["options"].get("ondelete") is None + foreign_key.get("options", {}).get("ondelete") is None ): alters.append( { @@ -319,7 +319,7 @@ def _drop_foreign_key_constraints(connection, engine, table, columns): for foreign_key in inspector.get_foreign_keys(table): if ( foreign_key["name"] - and foreign_key["options"].get("ondelete") + and foreign_key.get("options", {}).get("ondelete") and foreign_key["constrained_columns"] == columns ): drops.append(ForeignKeyConstraint((), (), name=foreign_key["name"])) From ed68a268ad4d1ce194896a291354d54228a89c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hjelseth=20H=C3=B8yer?= Date: Sat, 5 Jun 2021 11:50:56 +0200 Subject: [PATCH 05/17] Fix missing Tibber power production (#51505) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel Hjelseth Høyer --- homeassistant/components/tibber/sensor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/tibber/sensor.py b/homeassistant/components/tibber/sensor.py index b60d88e9814..660bbb741b0 100644 --- a/homeassistant/components/tibber/sensor.py +++ b/homeassistant/components/tibber/sensor.py @@ -45,6 +45,7 @@ SIGNAL_UPDATE_ENTITY = "tibber_rt_update_{}" RT_SENSOR_MAP = { "averagePower": ["average power", DEVICE_CLASS_POWER, POWER_WATT, None], "power": ["power", DEVICE_CLASS_POWER, POWER_WATT, None], + "powerProduction": ["power production", DEVICE_CLASS_POWER, POWER_WATT, None], "minPower": ["min power", DEVICE_CLASS_POWER, POWER_WATT, None], "maxPower": ["max power", DEVICE_CLASS_POWER, POWER_WATT, None], "accumulatedConsumption": [ From b21076c599dca8f2987f53c52c3a73ef1f5e88f7 Mon Sep 17 00:00:00 2001 From: Ron Klinkien Date: Sat, 5 Jun 2021 12:07:52 +0200 Subject: [PATCH 06/17] Bump garminconnect_aio to 0.1.4 (#51507) --- homeassistant/components/garmin_connect/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/garmin_connect/manifest.json b/homeassistant/components/garmin_connect/manifest.json index 2495249e4a4..22e115d0e06 100644 --- a/homeassistant/components/garmin_connect/manifest.json +++ b/homeassistant/components/garmin_connect/manifest.json @@ -2,7 +2,7 @@ "domain": "garmin_connect", "name": "Garmin Connect", "documentation": "https://www.home-assistant.io/integrations/garmin_connect", - "requirements": ["garminconnect_aio==0.1.1"], + "requirements": ["garminconnect_aio==0.1.4"], "codeowners": ["@cyberjunky"], "config_flow": true, "iot_class": "cloud_polling" diff --git a/requirements_all.txt b/requirements_all.txt index 43f477f9682..72f851f2215 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -635,7 +635,7 @@ gTTS==2.2.2 garages-amsterdam==2.1.1 # homeassistant.components.garmin_connect -garminconnect_aio==0.1.1 +garminconnect_aio==0.1.4 # homeassistant.components.geniushub geniushub-client==0.6.30 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 183124f95f0..cd7cde6e118 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -341,7 +341,7 @@ gTTS==2.2.2 garages-amsterdam==2.1.1 # homeassistant.components.garmin_connect -garminconnect_aio==0.1.1 +garminconnect_aio==0.1.4 # homeassistant.components.geo_json_events # homeassistant.components.usgs_earthquakes_feed From b06558fa0a4d6b87bb0faa1a1569d4fbbd84e069 Mon Sep 17 00:00:00 2001 From: Ludovico de Nittis Date: Sat, 5 Jun 2021 14:11:39 +0200 Subject: [PATCH 07/17] Bump pyialarm to 1.8.1 (#51519) --- homeassistant/components/ialarm/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ialarm/manifest.json b/homeassistant/components/ialarm/manifest.json index e112a26003e..08666129fd9 100644 --- a/homeassistant/components/ialarm/manifest.json +++ b/homeassistant/components/ialarm/manifest.json @@ -2,7 +2,7 @@ "domain": "ialarm", "name": "Antifurto365 iAlarm", "documentation": "https://www.home-assistant.io/integrations/ialarm", - "requirements": ["pyialarm==1.7"], + "requirements": ["pyialarm==1.8.1"], "codeowners": ["@RyuzakiKK"], "config_flow": true, "iot_class": "local_polling" diff --git a/requirements_all.txt b/requirements_all.txt index 72f851f2215..95589423c7f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1464,7 +1464,7 @@ pyhomematic==0.1.72 pyhomeworks==0.0.6 # homeassistant.components.ialarm -pyialarm==1.7 +pyialarm==1.8.1 # homeassistant.components.icloud pyicloud==0.10.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index cd7cde6e118..5f3171899e5 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -808,7 +808,7 @@ pyhiveapi==0.4.2 pyhomematic==0.1.72 # homeassistant.components.ialarm -pyialarm==1.7 +pyialarm==1.8.1 # homeassistant.components.icloud pyicloud==0.10.2 From 8818df06636f80ae9d19a740f77608517fc06a37 Mon Sep 17 00:00:00 2001 From: Malte Franken Date: Mon, 7 Jun 2021 04:03:56 +1000 Subject: [PATCH 08/17] Improve log message when zone missing in geolocation trigger (#51522) * log warning message if zone cannot be found * improve log message * add test case --- .../components/geo_location/trigger.py | 11 +++++ tests/components/geo_location/test_trigger.py | 45 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/homeassistant/components/geo_location/trigger.py b/homeassistant/components/geo_location/trigger.py index 3cdefccfeab..4410d39c0a6 100644 --- a/homeassistant/components/geo_location/trigger.py +++ b/homeassistant/components/geo_location/trigger.py @@ -1,4 +1,6 @@ """Offer geolocation automation rules.""" +import logging + import voluptuous as vol from homeassistant.components.geo_location import DOMAIN @@ -10,6 +12,8 @@ from homeassistant.helpers.event import TrackStates, async_track_state_change_fi # mypy: allow-untyped-defs, no-check-untyped-defs +_LOGGER = logging.getLogger(__name__) + EVENT_ENTER = "enter" EVENT_LEAVE = "leave" DEFAULT_EVENT = EVENT_ENTER @@ -49,6 +53,13 @@ async def async_attach_trigger(hass, config, action, automation_info): return zone_state = hass.states.get(zone_entity_id) + if zone_state is None: + _LOGGER.warning( + "Unable to execute automation %s: Zone %s not found", + automation_info["name"], + zone_entity_id, + ) + return from_match = ( condition.zone(hass, zone_state, from_state) if from_state else False diff --git a/tests/components/geo_location/test_trigger.py b/tests/components/geo_location/test_trigger.py index e40b134e657..bc74f01f6f1 100644 --- a/tests/components/geo_location/test_trigger.py +++ b/tests/components/geo_location/test_trigger.py @@ -1,4 +1,6 @@ """The tests for the geolocation trigger.""" +import logging + import pytest from homeassistant.components import automation, zone @@ -318,3 +320,46 @@ async def test_if_fires_on_zone_disappear(hass, calls): assert ( calls[0].data["some"] == "geo_location - geo_location.entity - hello - - test" ) + + +async def test_zone_undefined(hass, calls, caplog): + """Test for undefined zone.""" + hass.states.async_set( + "geo_location.entity", + "hello", + {"latitude": 32.880586, "longitude": -117.237564, "source": "test_source"}, + ) + await hass.async_block_till_done() + + caplog.set_level(logging.WARNING) + + zone_does_not_exist = "zone.does_not_exist" + assert await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: { + "trigger": { + "platform": "geo_location", + "source": "test_source", + "zone": zone_does_not_exist, + "event": "leave", + }, + "action": {"service": "test.automation"}, + } + }, + ) + + hass.states.async_set( + "geo_location.entity", + "hello", + {"latitude": 32.881011, "longitude": -117.234758, "source": "test_source"}, + ) + await hass.async_block_till_done() + + assert len(calls) == 0 + + assert ( + f"Unable to execute automation automation 0: Zone {zone_does_not_exist} not found" + in caplog.text + ) From b807b8754b50255cae5fbe7bb8eb19322581e36c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 5 Jun 2021 12:02:36 -1000 Subject: [PATCH 09/17] Ensure host is always set with samsungtv SSDP discovery (#51527) There was a case where self._host could have been None before _async_set_unique_id_from_udn was called Fixes #51186 --- .../components/samsungtv/config_flow.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/samsungtv/config_flow.py b/homeassistant/components/samsungtv/config_flow.py index 7c6dea56b96..a69a456df40 100644 --- a/homeassistant/components/samsungtv/config_flow.py +++ b/homeassistant/components/samsungtv/config_flow.py @@ -112,6 +112,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): async def _async_set_unique_id_from_udn(self, raise_on_progress=True): """Set the unique id from the udn.""" + assert self._host is not None await self.async_set_unique_id(self._udn, raise_on_progress=raise_on_progress) self._async_update_existing_host_entry(self._host) updates = {CONF_HOST: self._host} @@ -206,30 +207,28 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): return entry return None - async def _async_start_discovery_for_host(self, host): - """Start discovery for a host.""" - if entry := self._async_update_existing_host_entry(host): + async def _async_start_discovery(self): + """Start discovery.""" + assert self._host is not None + if entry := self._async_update_existing_host_entry(self._host): if entry.unique_id: # Let the flow continue to fill the missing # unique id as we may be able to obtain it # in the next step raise data_entry_flow.AbortFlow("already_configured") - self.context[CONF_HOST] = host + self.context[CONF_HOST] = self._host for progress in self._async_in_progress(): - if progress.get("context", {}).get(CONF_HOST) == host: + if progress.get("context", {}).get(CONF_HOST) == self._host: raise data_entry_flow.AbortFlow("already_in_progress") - self._host = host - async def async_step_ssdp(self, discovery_info: DiscoveryInfoType): """Handle a flow initialized by ssdp discovery.""" LOGGER.debug("Samsung device found via SSDP: %s", discovery_info) self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN]) + self._host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname await self._async_set_unique_id_from_udn() - await self._async_start_discovery_for_host( - urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname - ) + await self._async_start_discovery() self._manufacturer = discovery_info[ATTR_UPNP_MANUFACTURER] if not self._manufacturer or not self._manufacturer.lower().startswith( "samsung" @@ -245,7 +244,8 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a flow initialized by dhcp discovery.""" LOGGER.debug("Samsung device found via DHCP: %s", discovery_info) self._mac = discovery_info[MAC_ADDRESS] - await self._async_start_discovery_for_host(discovery_info[IP_ADDRESS]) + self._host = discovery_info[IP_ADDRESS] + await self._async_start_discovery() await self._async_set_device_unique_id() self.context["title_placeholders"] = {"device": self._title} return await self.async_step_confirm() @@ -254,7 +254,8 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a flow initialized by zeroconf discovery.""" LOGGER.debug("Samsung device found via ZEROCONF: %s", discovery_info) self._mac = format_mac(discovery_info[ATTR_PROPERTIES]["deviceid"]) - await self._async_start_discovery_for_host(discovery_info[CONF_HOST]) + self._host = discovery_info[CONF_HOST] + await self._async_start_discovery() await self._async_set_device_unique_id() self.context["title_placeholders"] = {"device": self._title} return await self.async_step_confirm() From 45d94c7fc8006204efe0073107b6c15697e9b3b7 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Sun, 6 Jun 2021 00:31:11 -0600 Subject: [PATCH 10/17] Bump aiorecollect to 1.0.5 (#51538) --- homeassistant/components/recollect_waste/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/recollect_waste/manifest.json b/homeassistant/components/recollect_waste/manifest.json index e33edcc2ab5..550612fbea2 100644 --- a/homeassistant/components/recollect_waste/manifest.json +++ b/homeassistant/components/recollect_waste/manifest.json @@ -3,7 +3,7 @@ "name": "ReCollect Waste", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/recollect_waste", - "requirements": ["aiorecollect==1.0.4"], + "requirements": ["aiorecollect==1.0.5"], "codeowners": ["@bachya"], "iot_class": "cloud_polling" } diff --git a/requirements_all.txt b/requirements_all.txt index 95589423c7f..9902a6ab31f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -224,7 +224,7 @@ aiopvpc==2.1.2 aiopylgtv==0.4.0 # homeassistant.components.recollect_waste -aiorecollect==1.0.4 +aiorecollect==1.0.5 # homeassistant.components.shelly aioshelly==0.6.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5f3171899e5..b2d64664395 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -146,7 +146,7 @@ aiopvpc==2.1.2 aiopylgtv==0.4.0 # homeassistant.components.recollect_waste -aiorecollect==1.0.4 +aiorecollect==1.0.5 # homeassistant.components.shelly aioshelly==0.6.4 From 5016fd9fa8ec3487177add55d3298f070c2d71f6 Mon Sep 17 00:00:00 2001 From: Ron Klinkien Date: Mon, 7 Jun 2021 10:09:08 +0200 Subject: [PATCH 11/17] Fix garmin_connect config flow multiple account creation (#51542) --- .../components/garmin_connect/config_flow.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/garmin_connect/config_flow.py b/homeassistant/components/garmin_connect/config_flow.py index 8e26e2bf608..8f83a9e1071 100644 --- a/homeassistant/components/garmin_connect/config_flow.py +++ b/homeassistant/components/garmin_connect/config_flow.py @@ -39,14 +39,14 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return await self._show_setup_form() websession = async_get_clientsession(self.hass) + username = user_input[CONF_USERNAME] + password = user_input[CONF_PASSWORD] - garmin_client = Garmin( - websession, user_input[CONF_USERNAME], user_input[CONF_PASSWORD] - ) + garmin_client = Garmin(websession, username, password) errors = {} try: - username = await garmin_client.login() + await garmin_client.login() except GarminConnectConnectionError: errors["base"] = "cannot_connect" return await self._show_setup_form(errors) @@ -68,7 +68,7 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): title=username, data={ CONF_ID: username, - CONF_USERNAME: user_input[CONF_USERNAME], - CONF_PASSWORD: user_input[CONF_PASSWORD], + CONF_USERNAME: username, + CONF_PASSWORD: password, }, ) From 619e37b6003fc8b3318108b35a3edc60fb9c1cf5 Mon Sep 17 00:00:00 2001 From: stephan192 Date: Mon, 7 Jun 2021 10:53:36 +0200 Subject: [PATCH 12/17] Bump dwdwfsapi to 1.0.4 (#51556) --- homeassistant/components/dwd_weather_warnings/manifest.json | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/dwd_weather_warnings/manifest.json b/homeassistant/components/dwd_weather_warnings/manifest.json index 1550d9262a4..55c848ea219 100644 --- a/homeassistant/components/dwd_weather_warnings/manifest.json +++ b/homeassistant/components/dwd_weather_warnings/manifest.json @@ -3,6 +3,6 @@ "name": "Deutscher Wetterdienst (DWD) Weather Warnings", "documentation": "https://www.home-assistant.io/integrations/dwd_weather_warnings", "codeowners": ["@runningman84", "@stephan192", "@Hummel95"], - "requirements": ["dwdwfsapi==1.0.3"], + "requirements": ["dwdwfsapi==1.0.4"], "iot_class": "cloud_polling" } diff --git a/requirements_all.txt b/requirements_all.txt index 9902a6ab31f..48e5632b730 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -515,7 +515,7 @@ dovado==0.4.1 dsmr_parser==0.29 # homeassistant.components.dwd_weather_warnings -dwdwfsapi==1.0.3 +dwdwfsapi==1.0.4 # homeassistant.components.dweet dweepy==0.3.0 From 03f10333c44531e01cc35d32c54d670f74244a9f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 6 Jun 2021 23:49:37 -1000 Subject: [PATCH 13/17] Increase isy setup timeout to 60s (#51559) - Ensure errors are displayed in the UI --- homeassistant/components/isy994/__init__.py | 25 +++++++++------------ 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/isy994/__init__.py b/homeassistant/components/isy994/__init__.py index 99905e4d946..51c34aeb0a7 100644 --- a/homeassistant/components/isy994/__init__.py +++ b/homeassistant/components/isy994/__init__.py @@ -172,14 +172,12 @@ async def async_setup_entry( ) try: - async with async_timeout.timeout(30): + async with async_timeout.timeout(60): await isy.initialize() except asyncio.TimeoutError as err: - _LOGGER.error( - "Timed out initializing the ISY; device may be busy, trying again later: %s", - err, - ) - raise ConfigEntryNotReady from err + raise ConfigEntryNotReady( + f"Timed out initializing the ISY; device may be busy, trying again later: {err}" + ) from err except ISYInvalidAuthError as err: _LOGGER.error( "Invalid credentials for the ISY, please adjust settings and try again: %s", @@ -187,16 +185,13 @@ async def async_setup_entry( ) return False except ISYConnectionError as err: - _LOGGER.error( - "Failed to connect to the ISY, please adjust settings and try again: %s", - err, - ) - raise ConfigEntryNotReady from err + raise ConfigEntryNotReady( + f"Failed to connect to the ISY, please adjust settings and try again: {err}" + ) from err except ISYResponseParseError as err: - _LOGGER.warning( - "Error processing responses from the ISY; device may be busy, trying again later" - ) - raise ConfigEntryNotReady from err + raise ConfigEntryNotReady( + f"Invalid XML response from ISY; Ensure the ISY is running the latest firmware: {err}" + ) from err _categorize_nodes(hass_isy_data, isy.nodes, ignore_identifier, sensor_identifier) _categorize_programs(hass_isy_data, isy.programs) From bd24431930ebfe39d31a61897c3c581fb527bce7 Mon Sep 17 00:00:00 2001 From: jjlawren Date: Mon, 7 Jun 2021 04:46:56 -0500 Subject: [PATCH 14/17] Fix Sonos restore calls (#51565) --- homeassistant/components/sonos/speaker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sonos/speaker.py b/homeassistant/components/sonos/speaker.py index 957851dfbee..58598648992 100644 --- a/homeassistant/components/sonos/speaker.py +++ b/homeassistant/components/sonos/speaker.py @@ -764,7 +764,7 @@ class SonosSpeaker: """Pause all current coordinators and restore groups.""" for speaker in (s for s in speakers if s.is_coordinator): if speaker.media.playback_status == SONOS_STATE_PLAYING: - hass.async_create_task(speaker.soco.pause()) + speaker.soco.pause() groups = [] From 70f4907414bd8104040a95eb446257d5cccb4b00 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 7 Jun 2021 19:16:47 +0200 Subject: [PATCH 15/17] Update builder to 2021.06.2 (#51582) --- .github/workflows/builder.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/builder.yml b/.github/workflows/builder.yml index 190c449cf3c..607af99fb51 100644 --- a/.github/workflows/builder.yml +++ b/.github/workflows/builder.yml @@ -115,7 +115,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build base image - uses: home-assistant/builder@2021.05.0 + uses: home-assistant/builder@2021.06.2 with: args: | $BUILD_ARGS \ @@ -167,7 +167,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build base image - uses: home-assistant/builder@2021.05.0 + uses: home-assistant/builder@2021.06.2 with: args: | $BUILD_ARGS \ From 4dd875199f98c2009030aeebdd9913b0f12c9bab Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 7 Jun 2021 23:14:42 +0200 Subject: [PATCH 16/17] Fix deprecated value_template for MQTT light (#51587) --- homeassistant/components/mqtt/light/schema_basic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/mqtt/light/schema_basic.py b/homeassistant/components/mqtt/light/schema_basic.py index 3e347363428..684dcf337aa 100644 --- a/homeassistant/components/mqtt/light/schema_basic.py +++ b/homeassistant/components/mqtt/light/schema_basic.py @@ -186,9 +186,6 @@ async def async_setup_entity_basic( hass, config, async_add_entities, config_entry, discovery_data=None ): """Set up a MQTT Light.""" - if CONF_STATE_VALUE_TEMPLATE not in config and CONF_VALUE_TEMPLATE in config: - config[CONF_STATE_VALUE_TEMPLATE] = config[CONF_VALUE_TEMPLATE] - async_add_entities([MqttLight(hass, config, config_entry, discovery_data)]) @@ -236,6 +233,9 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity): def _setup_from_config(self, config): """(Re)Setup the entity.""" + if CONF_STATE_VALUE_TEMPLATE not in config and CONF_VALUE_TEMPLATE in config: + config[CONF_STATE_VALUE_TEMPLATE] = config[CONF_VALUE_TEMPLATE] + topic = { key: config.get(key) for key in ( From 6b38480caffc41bf1ba7c9b8a4a2422e8789f150 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 7 Jun 2021 14:15:39 -0700 Subject: [PATCH 17/17] Bumped version to 2021.6.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 87e53643240..3b1fc4705a8 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -5,7 +5,7 @@ from typing import Final MAJOR_VERSION: Final = 2021 MINOR_VERSION: Final = 6 -PATCH_VERSION: Final = "2" +PATCH_VERSION: Final = "3" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)