From 6e688b2b7f8f530c3d555af1b7b07936414646ec Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 10 Aug 2022 13:51:31 -0600 Subject: [PATCH 01/10] Bump ZHA dependencies (#76565) --- homeassistant/components/zha/manifest.json | 4 ++-- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index bad84054f1f..1eb2536fed6 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -4,12 +4,12 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ - "bellows==0.31.3", + "bellows==0.32.0", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.78", "zigpy-deconz==0.18.0", - "zigpy==0.49.0", + "zigpy==0.49.1", "zigpy-xbee==0.15.0", "zigpy-zigate==0.9.1", "zigpy-znp==0.8.1" diff --git a/requirements_all.txt b/requirements_all.txt index c5254b61842..1d078b34966 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -396,7 +396,7 @@ beautifulsoup4==4.11.1 # beewi_smartclim==0.0.10 # homeassistant.components.zha -bellows==0.31.3 +bellows==0.32.0 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.1 @@ -2535,7 +2535,7 @@ zigpy-zigate==0.9.1 zigpy-znp==0.8.1 # homeassistant.components.zha -zigpy==0.49.0 +zigpy==0.49.1 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c64f4506850..a3c3cf9ac48 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -320,7 +320,7 @@ base36==0.1.1 beautifulsoup4==4.11.1 # homeassistant.components.zha -bellows==0.31.3 +bellows==0.32.0 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.1 @@ -1709,7 +1709,7 @@ zigpy-zigate==0.9.1 zigpy-znp==0.8.1 # homeassistant.components.zha -zigpy==0.49.0 +zigpy==0.49.1 # homeassistant.components.zwave_js zwave-js-server-python==0.39.0 From 2dcc886b2f716148cb4270b107c5d08279badfb0 Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 10 Aug 2022 23:57:58 +0200 Subject: [PATCH 02/10] Replaces aiohttp.hdrs CONTENT_TYPE with plain string for the Swisscom integration (#76568) --- homeassistant/components/swisscom/device_tracker.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/swisscom/device_tracker.py b/homeassistant/components/swisscom/device_tracker.py index 3c8e7341be2..d95067e6b33 100644 --- a/homeassistant/components/swisscom/device_tracker.py +++ b/homeassistant/components/swisscom/device_tracker.py @@ -4,7 +4,6 @@ from __future__ import annotations from contextlib import suppress import logging -from aiohttp.hdrs import CONTENT_TYPE import requests import voluptuous as vol @@ -79,7 +78,7 @@ class SwisscomDeviceScanner(DeviceScanner): def get_swisscom_data(self): """Retrieve data from Swisscom and return parsed result.""" url = f"http://{self.host}/ws" - headers = {CONTENT_TYPE: "application/x-sah-ws-4-call+json"} + headers = {"Content-Type": "application/x-sah-ws-4-call+json"} data = """ {"service":"Devices", "method":"get", "parameters":{"expression":"lan and not self"}}""" From a3ea881a0161e8603e20f852d1666862c0591589 Mon Sep 17 00:00:00 2001 From: Jc2k Date: Thu, 11 Aug 2022 02:35:05 +0100 Subject: [PATCH 03/10] Fix homekit_controller not noticing ip and port changes that zeroconf has found (#76570) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index cf3069e3b0d..4bd9a0b70f9 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -3,7 +3,7 @@ "name": "HomeKit Controller", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/homekit_controller", - "requirements": ["aiohomekit==1.2.8"], + "requirements": ["aiohomekit==1.2.9"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."], "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }], "dependencies": ["bluetooth", "zeroconf"], diff --git a/requirements_all.txt b/requirements_all.txt index 1d078b34966..c0a8eddb705 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -168,7 +168,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.2.8 +aiohomekit==1.2.9 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a3c3cf9ac48..92816e5efd4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -152,7 +152,7 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.2.8 +aiohomekit==1.2.9 # homeassistant.components.emulated_hue # homeassistant.components.http From 738423056e6af8f1c695badda7732f63ead2e118 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 11 Aug 2022 03:27:52 +0200 Subject: [PATCH 04/10] Fix Spotify deviding None value in current progress (#76581) --- homeassistant/components/spotify/media_player.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/spotify/media_player.py b/homeassistant/components/spotify/media_player.py index 04f523c2d4b..5fcb5f28264 100644 --- a/homeassistant/components/spotify/media_player.py +++ b/homeassistant/components/spotify/media_player.py @@ -180,7 +180,10 @@ class SpotifyMediaPlayer(MediaPlayerEntity): @property def media_position(self) -> int | None: """Position of current playing media in seconds.""" - if not self._currently_playing: + if ( + not self._currently_playing + or self._currently_playing.get("progress_ms") is None + ): return None return self._currently_playing["progress_ms"] / 1000 From 451ab47caaaf69554193bc7caf3384522d1ede15 Mon Sep 17 00:00:00 2001 From: Antonino Piazza Date: Thu, 11 Aug 2022 11:03:12 +0200 Subject: [PATCH 05/10] Improve code quality in huawei_lte (#76583) Co-authored-by: Martin Hjelmare --- .../components/huawei_lte/__init__.py | 9 +- homeassistant/components/huawei_lte/switch.py | 4 +- tests/components/huawei_lte/test_switches.py | 182 ++++++++++-------- 3 files changed, 107 insertions(+), 88 deletions(-) diff --git a/homeassistant/components/huawei_lte/__init__.py b/homeassistant/components/huawei_lte/__init__.py index bace633f128..565286c4505 100644 --- a/homeassistant/components/huawei_lte/__init__.py +++ b/homeassistant/components/huawei_lte/__init__.py @@ -279,11 +279,12 @@ class Router: self._get_data( KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH, lambda: next( - filter( - lambda ssid: ssid.get("wifiisguestnetwork") == "1", - self.client.wlan.multi_basic_settings() + ( + ssid + for ssid in self.client.wlan.multi_basic_settings() .get("Ssids", {}) - .get("Ssid", []), + .get("Ssid", []) + if isinstance(ssid, dict) and ssid.get("wifiisguestnetwork") == "1" ), {}, ), diff --git a/homeassistant/components/huawei_lte/switch.py b/homeassistant/components/huawei_lte/switch.py index 78579d62698..261b77987cf 100644 --- a/homeassistant/components/huawei_lte/switch.py +++ b/homeassistant/components/huawei_lte/switch.py @@ -37,7 +37,7 @@ async def async_setup_entry( if router.data.get(KEY_DIALUP_MOBILE_DATASWITCH): switches.append(HuaweiLteMobileDataSwitch(router)) - if router.data.get(KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH).get("WifiEnable"): + if router.data.get(KEY_WLAN_WIFI_GUEST_NETWORK_SWITCH, {}).get("WifiEnable"): switches.append(HuaweiLteWifiGuestNetworkSwitch(router)) async_add_entities(switches, True) @@ -151,6 +151,6 @@ class HuaweiLteWifiGuestNetworkSwitch(HuaweiLteBaseSwitch): return "mdi:wifi" if self.is_on else "mdi:wifi-off" @property - def extra_state_attributes(self) -> dict[str, str]: + def extra_state_attributes(self) -> dict[str, str | None]: """Return the state attributes.""" return {"ssid": self.router.data[self.key].get("WifiSsid")} diff --git a/tests/components/huawei_lte/test_switches.py b/tests/components/huawei_lte/test_switches.py index 5bafed27e70..4b0b81a86cd 100644 --- a/tests/components/huawei_lte/test_switches.py +++ b/tests/components/huawei_lte/test_switches.py @@ -2,7 +2,6 @@ from unittest.mock import MagicMock, patch from huawei_lte_api.enums.cradle import ConnectionStatusEnum -from pytest import fixture from homeassistant.components.huawei_lte.const import DOMAIN from homeassistant.components.switch import ( @@ -20,94 +19,70 @@ from tests.common import MockConfigEntry SWITCH_WIFI_GUEST_NETWORK = "switch.lte_wifi_guest_network" -@fixture +def magic_client(multi_basic_settings_value: dict) -> MagicMock: + """Mock huawei_lte.Client.""" + information = MagicMock(return_value={"SerialNumber": "test-serial-number"}) + check_notifications = MagicMock(return_value={"SmsStorageFull": 0}) + status = MagicMock( + return_value={"ConnectionStatus": ConnectionStatusEnum.CONNECTED.value} + ) + multi_basic_settings = MagicMock(return_value=multi_basic_settings_value) + wifi_feature_switch = MagicMock(return_value={"wifi24g_switch_enable": 1}) + device = MagicMock(information=information) + monitoring = MagicMock(check_notifications=check_notifications, status=status) + wlan = MagicMock( + multi_basic_settings=multi_basic_settings, + wifi_feature_switch=wifi_feature_switch, + ) + return MagicMock(device=device, monitoring=monitoring, wlan=wlan) + + @patch("homeassistant.components.huawei_lte.Connection", MagicMock()) -@patch( - "homeassistant.components.huawei_lte.Client", - return_value=MagicMock( - device=MagicMock( - information=MagicMock(return_value={"SerialNumber": "test-serial-number"}) - ), - monitoring=MagicMock( - check_notifications=MagicMock(return_value={"SmsStorageFull": 0}), - status=MagicMock( - return_value={"ConnectionStatus": ConnectionStatusEnum.CONNECTED.value} - ), - ), - wlan=MagicMock( - multi_basic_settings=MagicMock( - return_value={ - "Ssids": {"Ssid": [{"wifiisguestnetwork": "1", "WifiEnable": "0"}]} - } - ), - wifi_feature_switch=MagicMock(return_value={"wifi24g_switch_enable": 1}), - ), - ), -) -async def setup_component_with_wifi_guest_network( - client: MagicMock, hass: HomeAssistant -) -> None: - """Initialize huawei_lte components.""" - assert client - huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) - huawei_lte.add_to_hass(hass) - assert await hass.config_entries.async_setup(huawei_lte.entry_id) - await hass.async_block_till_done() - - -@fixture -@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) -@patch( - "homeassistant.components.huawei_lte.Client", - return_value=MagicMock( - device=MagicMock( - information=MagicMock(return_value={"SerialNumber": "test-serial-number"}) - ), - monitoring=MagicMock( - check_notifications=MagicMock(return_value={"SmsStorageFull": 0}), - status=MagicMock( - return_value={"ConnectionStatus": ConnectionStatusEnum.CONNECTED.value} - ), - ), - wlan=MagicMock( - multi_basic_settings=MagicMock(return_value={}), - wifi_feature_switch=MagicMock(return_value={"wifi24g_switch_enable": 1}), - ), - ), -) -async def setup_component_without_wifi_guest_network( - client: MagicMock, hass: HomeAssistant -) -> None: - """Initialize huawei_lte components.""" - assert client - huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) - huawei_lte.add_to_hass(hass) - assert await hass.config_entries.async_setup(huawei_lte.entry_id) - await hass.async_block_till_done() - - -def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_not_present( +@patch("homeassistant.components.huawei_lte.Client", return_value=magic_client({})) +async def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_not_present( + client, hass: HomeAssistant, - setup_component_without_wifi_guest_network, ) -> None: """Test switch wifi guest network config entry when network is not present.""" + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() entity_registry: EntityRegistry = er.async_get(hass) assert not entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) -def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_present( +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch( + "homeassistant.components.huawei_lte.Client", + return_value=magic_client( + {"Ssids": {"Ssid": [{"wifiisguestnetwork": "1", "WifiEnable": "0"}]}} + ), +) +async def test_huawei_lte_wifi_guest_network_config_entry_when_network_is_present( + client, hass: HomeAssistant, - setup_component_with_wifi_guest_network, ) -> None: """Test switch wifi guest network config entry when network is present.""" + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() entity_registry: EntityRegistry = er.async_get(hass) assert entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) -async def test_turn_on_switch_wifi_guest_network( - hass: HomeAssistant, setup_component_with_wifi_guest_network -) -> None: +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch("homeassistant.components.huawei_lte.Client") +async def test_turn_on_switch_wifi_guest_network(client, hass: HomeAssistant) -> None: """Test switch wifi guest network turn on method.""" + client.return_value = magic_client( + {"Ssids": {"Ssid": [{"wifiisguestnetwork": "1", "WifiEnable": "0"}]}} + ) + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_ON, @@ -116,15 +91,20 @@ async def test_turn_on_switch_wifi_guest_network( ) await hass.async_block_till_done() assert hass.states.is_state(SWITCH_WIFI_GUEST_NETWORK, STATE_ON) - hass.data[DOMAIN].routers[ - "test-serial-number" - ].client.wlan.wifi_guest_network_switch.assert_called_once_with(True) + client.return_value.wlan.wifi_guest_network_switch.assert_called_once_with(True) -async def test_turn_off_switch_wifi_guest_network( - hass: HomeAssistant, setup_component_with_wifi_guest_network -) -> None: +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch("homeassistant.components.huawei_lte.Client") +async def test_turn_off_switch_wifi_guest_network(client, hass: HomeAssistant) -> None: """Test switch wifi guest network turn off method.""" + client.return_value = magic_client( + {"Ssids": {"Ssid": [{"wifiisguestnetwork": "1", "WifiEnable": "1"}]}} + ) + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() await hass.services.async_call( SWITCH_DOMAIN, SERVICE_TURN_OFF, @@ -133,6 +113,44 @@ async def test_turn_off_switch_wifi_guest_network( ) await hass.async_block_till_done() assert hass.states.is_state(SWITCH_WIFI_GUEST_NETWORK, STATE_OFF) - hass.data[DOMAIN].routers[ - "test-serial-number" - ].client.wlan.wifi_guest_network_switch.assert_called_with(False) + client.return_value.wlan.wifi_guest_network_switch.assert_called_with(False) + + +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch( + "homeassistant.components.huawei_lte.Client", + return_value=magic_client({"Ssids": {"Ssid": "str"}}), +) +async def test_huawei_lte_wifi_guest_network_config_entry_when_ssid_is_str( + client, hass: HomeAssistant +): + """Test switch wifi guest network config entry when ssid is a str. + + Issue #76244. Huawai models: H312-371, E5372 and E8372. + """ + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() + entity_registry: EntityRegistry = er.async_get(hass) + assert not entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) + + +@patch("homeassistant.components.huawei_lte.Connection", MagicMock()) +@patch( + "homeassistant.components.huawei_lte.Client", + return_value=magic_client({"Ssids": {"Ssid": None}}), +) +async def test_huawei_lte_wifi_guest_network_config_entry_when_ssid_is_none( + client, hass: HomeAssistant +): + """Test switch wifi guest network config entry when ssid is a None. + + Issue #76244. + """ + huawei_lte = MockConfigEntry(domain=DOMAIN, data={CONF_URL: "http://huawei-lte"}) + huawei_lte.add_to_hass(hass) + await hass.config_entries.async_setup(huawei_lte.entry_id) + await hass.async_block_till_done() + entity_registry: EntityRegistry = er.async_get(hass) + assert not entity_registry.async_is_registered(SWITCH_WIFI_GUEST_NETWORK) From 99c20223e5271244e27c4313ed1c6a953c648e62 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 10 Aug 2022 23:08:03 -1000 Subject: [PATCH 06/10] Fix Govee 5181 with old firmware (#76600) --- homeassistant/components/govee_ble/manifest.json | 6 +++++- homeassistant/generated/bluetooth.py | 5 +++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/govee_ble/manifest.json b/homeassistant/components/govee_ble/manifest.json index 2ba97b95d08..74917e3ca14 100644 --- a/homeassistant/components/govee_ble/manifest.json +++ b/homeassistant/components/govee_ble/manifest.json @@ -19,6 +19,10 @@ "manufacturer_id": 818, "service_uuid": "00008551-0000-1000-8000-00805f9b34fb" }, + { + "manufacturer_id": 59970, + "service_uuid": "00008151-0000-1000-8000-00805f9b34fb" + }, { "manufacturer_id": 14474, "service_uuid": "00008151-0000-1000-8000-00805f9b34fb" @@ -28,7 +32,7 @@ "service_uuid": "00008251-0000-1000-8000-00805f9b34fb" } ], - "requirements": ["govee-ble==0.14.0"], + "requirements": ["govee-ble==0.14.1"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "iot_class": "local_push" diff --git a/homeassistant/generated/bluetooth.py b/homeassistant/generated/bluetooth.py index 15a822599c6..4f46ded6936 100644 --- a/homeassistant/generated/bluetooth.py +++ b/homeassistant/generated/bluetooth.py @@ -46,6 +46,11 @@ BLUETOOTH: list[dict[str, str | int | list[int]]] = [ "manufacturer_id": 818, "service_uuid": "00008551-0000-1000-8000-00805f9b34fb" }, + { + "domain": "govee_ble", + "manufacturer_id": 59970, + "service_uuid": "00008151-0000-1000-8000-00805f9b34fb" + }, { "domain": "govee_ble", "manufacturer_id": 14474, diff --git a/requirements_all.txt b/requirements_all.txt index c0a8eddb705..96be4dae1b1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -760,7 +760,7 @@ googlemaps==2.5.1 goslide-api==0.5.1 # homeassistant.components.govee_ble -govee-ble==0.14.0 +govee-ble==0.14.1 # homeassistant.components.remote_rpi_gpio gpiozero==1.6.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 92816e5efd4..59b922c4ef1 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -561,7 +561,7 @@ google-nest-sdm==2.0.0 googlemaps==2.5.1 # homeassistant.components.govee_ble -govee-ble==0.14.0 +govee-ble==0.14.1 # homeassistant.components.gree greeclimate==1.3.0 From 294cc3ac6e3917b810b70c0d2b89793d0069c9b7 Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Thu, 11 Aug 2022 14:53:40 +0200 Subject: [PATCH 07/10] Fix evohome preset modes (#76606) --- homeassistant/components/evohome/climate.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/evohome/climate.py b/homeassistant/components/evohome/climate.py index c1a630d0d05..e9eab8c2ae3 100644 --- a/homeassistant/components/evohome/climate.py +++ b/homeassistant/components/evohome/climate.py @@ -128,26 +128,17 @@ class EvoClimateEntity(EvoDevice, ClimateEntity): _attr_temperature_unit = TEMP_CELSIUS - def __init__(self, evo_broker, evo_device) -> None: - """Initialize a Climate device.""" - super().__init__(evo_broker, evo_device) - - self._preset_modes = None - @property def hvac_modes(self) -> list[str]: """Return a list of available hvac operation modes.""" return list(HA_HVAC_TO_TCS) - @property - def preset_modes(self) -> list[str] | None: - """Return a list of available preset modes.""" - return self._preset_modes - class EvoZone(EvoChild, EvoClimateEntity): """Base for a Honeywell TCC Zone.""" + _attr_preset_modes = list(HA_PRESET_TO_EVO) + def __init__(self, evo_broker, evo_device) -> None: """Initialize a Honeywell TCC Zone.""" super().__init__(evo_broker, evo_device) @@ -233,7 +224,7 @@ class EvoZone(EvoChild, EvoClimateEntity): """ return self._evo_device.setpointCapabilities["maxHeatSetpoint"] - async def async_set_temperature(self, **kwargs) -> None: + async def async_set_temperature(self, **kwargs: Any) -> None: """Set a new target temperature.""" temperature = kwargs["temperature"] @@ -249,7 +240,7 @@ class EvoZone(EvoChild, EvoClimateEntity): self._evo_device.set_temperature(temperature, until=until) ) - async def async_set_hvac_mode(self, hvac_mode: str) -> None: + async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: """Set a Zone to one of its native EVO_* operating modes. Zones inherit their _effective_ operating mode from their Controller. @@ -387,7 +378,7 @@ class EvoController(EvoClimateEntity): """Return the current preset mode, e.g., home, away, temp.""" return TCS_PRESET_TO_HA.get(self._evo_tcs.systemModeStatus["mode"]) - async def async_set_temperature(self, **kwargs) -> None: + async def async_set_temperature(self, **kwargs: Any) -> None: """Raise exception as Controllers don't have a target temperature.""" raise NotImplementedError("Evohome Controllers don't have target temperatures.") From 84b8029c6a6572fbb4e64cf29c45cfe847999d82 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 11 Aug 2022 13:55:52 -1000 Subject: [PATCH 08/10] Add missing _abort_if_unique_id_configured to ble integrations (#76624) --- .../components/govee_ble/config_flow.py | 1 + .../components/inkbird/config_flow.py | 1 + homeassistant/components/moat/config_flow.py | 1 + .../components/sensorpush/config_flow.py | 1 + .../components/xiaomi_ble/config_flow.py | 1 + .../components/govee_ble/test_config_flow.py | 30 +++++++++++++++++++ tests/components/inkbird/test_config_flow.py | 28 +++++++++++++++++ tests/components/moat/test_config_flow.py | 28 +++++++++++++++++ .../components/sensorpush/test_config_flow.py | 30 +++++++++++++++++++ .../components/xiaomi_ble/test_config_flow.py | 30 +++++++++++++++++++ 10 files changed, 151 insertions(+) diff --git a/homeassistant/components/govee_ble/config_flow.py b/homeassistant/components/govee_ble/config_flow.py index 1e3a5566bfd..47d73f2779a 100644 --- a/homeassistant/components/govee_ble/config_flow.py +++ b/homeassistant/components/govee_ble/config_flow.py @@ -67,6 +67,7 @@ class GoveeConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: address = user_input[CONF_ADDRESS] await self.async_set_unique_id(address, raise_on_progress=False) + self._abort_if_unique_id_configured() return self.async_create_entry( title=self._discovered_devices[address], data={} ) diff --git a/homeassistant/components/inkbird/config_flow.py b/homeassistant/components/inkbird/config_flow.py index 21ed85e117e..524471bbcc7 100644 --- a/homeassistant/components/inkbird/config_flow.py +++ b/homeassistant/components/inkbird/config_flow.py @@ -67,6 +67,7 @@ class INKBIRDConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: address = user_input[CONF_ADDRESS] await self.async_set_unique_id(address, raise_on_progress=False) + self._abort_if_unique_id_configured() return self.async_create_entry( title=self._discovered_devices[address], data={} ) diff --git a/homeassistant/components/moat/config_flow.py b/homeassistant/components/moat/config_flow.py index 6f51b62d110..0e1b4f89568 100644 --- a/homeassistant/components/moat/config_flow.py +++ b/homeassistant/components/moat/config_flow.py @@ -67,6 +67,7 @@ class MoatConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: address = user_input[CONF_ADDRESS] await self.async_set_unique_id(address, raise_on_progress=False) + self._abort_if_unique_id_configured() return self.async_create_entry( title=self._discovered_devices[address], data={} ) diff --git a/homeassistant/components/sensorpush/config_flow.py b/homeassistant/components/sensorpush/config_flow.py index d10c2f481a6..63edd59a5b7 100644 --- a/homeassistant/components/sensorpush/config_flow.py +++ b/homeassistant/components/sensorpush/config_flow.py @@ -67,6 +67,7 @@ class SensorPushConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: address = user_input[CONF_ADDRESS] await self.async_set_unique_id(address, raise_on_progress=False) + self._abort_if_unique_id_configured() return self.async_create_entry( title=self._discovered_devices[address], data={} ) diff --git a/homeassistant/components/xiaomi_ble/config_flow.py b/homeassistant/components/xiaomi_ble/config_flow.py index a05e703db6a..4ec3b66d0f9 100644 --- a/homeassistant/components/xiaomi_ble/config_flow.py +++ b/homeassistant/components/xiaomi_ble/config_flow.py @@ -205,6 +205,7 @@ class XiaomiConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: address = user_input[CONF_ADDRESS] await self.async_set_unique_id(address, raise_on_progress=False) + self._abort_if_unique_id_configured() discovery = self._discovered_devices[address] self.context["title_placeholders"] = {"name": discovery.title} diff --git a/tests/components/govee_ble/test_config_flow.py b/tests/components/govee_ble/test_config_flow.py index a1b9fed3cd7..188672cdf18 100644 --- a/tests/components/govee_ble/test_config_flow.py +++ b/tests/components/govee_ble/test_config_flow.py @@ -78,6 +78,36 @@ async def test_async_step_user_with_found_devices(hass): assert result2["result"].unique_id == "4125DDBA-2774-4851-9889-6AADDD4CAC3D" +async def test_async_step_user_device_added_between_steps(hass): + """Test the device gets added via another flow between steps.""" + with patch( + "homeassistant.components.govee_ble.config_flow.async_discovered_service_info", + return_value=[GVH5177_SERVICE_INFO], + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="4125DDBA-2774-4851-9889-6AADDD4CAC3D", + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.govee_ble.async_setup_entry", return_value=True + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "4125DDBA-2774-4851-9889-6AADDD4CAC3D"}, + ) + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" + + async def test_async_step_user_with_found_devices_already_setup(hass): """Test setup from service info cache with devices found.""" entry = MockConfigEntry( diff --git a/tests/components/inkbird/test_config_flow.py b/tests/components/inkbird/test_config_flow.py index c1f8b3ef545..fe210f75f4b 100644 --- a/tests/components/inkbird/test_config_flow.py +++ b/tests/components/inkbird/test_config_flow.py @@ -74,6 +74,34 @@ async def test_async_step_user_with_found_devices(hass): assert result2["result"].unique_id == "61DE521B-F0BF-9F44-64D4-75BBE1738105" +async def test_async_step_user_device_added_between_steps(hass): + """Test the device gets added via another flow between steps.""" + with patch( + "homeassistant.components.inkbird.config_flow.async_discovered_service_info", + return_value=[SPS_SERVICE_INFO], + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="61DE521B-F0BF-9F44-64D4-75BBE1738105", + ) + entry.add_to_hass(hass) + + with patch("homeassistant.components.inkbird.async_setup_entry", return_value=True): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "61DE521B-F0BF-9F44-64D4-75BBE1738105"}, + ) + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" + + async def test_async_step_user_with_found_devices_already_setup(hass): """Test setup from service info cache with devices found.""" entry = MockConfigEntry( diff --git a/tests/components/moat/test_config_flow.py b/tests/components/moat/test_config_flow.py index 7ceeb2ad73f..6e92be703a2 100644 --- a/tests/components/moat/test_config_flow.py +++ b/tests/components/moat/test_config_flow.py @@ -74,6 +74,34 @@ async def test_async_step_user_with_found_devices(hass): assert result2["result"].unique_id == "aa:bb:cc:dd:ee:ff" +async def test_async_step_user_device_added_between_steps(hass): + """Test the device gets added via another flow between steps.""" + with patch( + "homeassistant.components.moat.config_flow.async_discovered_service_info", + return_value=[MOAT_S2_SERVICE_INFO], + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="aa:bb:cc:dd:ee:ff", + ) + entry.add_to_hass(hass) + + with patch("homeassistant.components.moat.async_setup_entry", return_value=True): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "aa:bb:cc:dd:ee:ff"}, + ) + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" + + async def test_async_step_user_with_found_devices_already_setup(hass): """Test setup from service info cache with devices found.""" entry = MockConfigEntry( diff --git a/tests/components/sensorpush/test_config_flow.py b/tests/components/sensorpush/test_config_flow.py index 1c825640603..244787eecb9 100644 --- a/tests/components/sensorpush/test_config_flow.py +++ b/tests/components/sensorpush/test_config_flow.py @@ -78,6 +78,36 @@ async def test_async_step_user_with_found_devices(hass): assert result2["result"].unique_id == "61DE521B-F0BF-9F44-64D4-75BBE1738105" +async def test_async_step_user_device_added_between_steps(hass): + """Test the device gets added via another flow between steps.""" + with patch( + "homeassistant.components.sensorpush.config_flow.async_discovered_service_info", + return_value=[HTW_SERVICE_INFO], + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="61DE521B-F0BF-9F44-64D4-75BBE1738105", + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.sensorpush.async_setup_entry", return_value=True + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "61DE521B-F0BF-9F44-64D4-75BBE1738105"}, + ) + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" + + async def test_async_step_user_with_found_devices_already_setup(hass): """Test setup from service info cache with devices found.""" entry = MockConfigEntry( diff --git a/tests/components/xiaomi_ble/test_config_flow.py b/tests/components/xiaomi_ble/test_config_flow.py index 32ba6be3322..2da3ce7140d 100644 --- a/tests/components/xiaomi_ble/test_config_flow.py +++ b/tests/components/xiaomi_ble/test_config_flow.py @@ -708,6 +708,36 @@ async def test_async_step_user_with_found_devices_legacy_encryption_wrong_key_le assert result2["result"].unique_id == "F8:24:41:C5:98:8B" +async def test_async_step_user_device_added_between_steps(hass): + """Test the device gets added via another flow between steps.""" + with patch( + "homeassistant.components.xiaomi_ble.config_flow.async_discovered_service_info", + return_value=[LYWSDCGQ_SERVICE_INFO], + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_USER}, + ) + assert result["type"] == FlowResultType.FORM + assert result["step_id"] == "user" + + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="58:2D:34:35:93:21", + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.xiaomi_ble.async_setup_entry", return_value=True + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={"address": "58:2D:34:35:93:21"}, + ) + assert result2["type"] == FlowResultType.ABORT + assert result2["reason"] == "already_configured" + + async def test_async_step_user_with_found_devices_already_setup(hass): """Test setup from service info cache with devices found.""" entry = MockConfigEntry( From 5606b4026f1412a39204cd7d4fb42cb9fef9d752 Mon Sep 17 00:00:00 2001 From: rikroe <42204099+rikroe@users.noreply.github.com> Date: Fri, 12 Aug 2022 15:19:16 +0200 Subject: [PATCH 09/10] Fix non-awaited coroutine in BMW notify (#76664) Co-authored-by: rikroe --- homeassistant/components/bmw_connected_drive/notify.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/bmw_connected_drive/notify.py b/homeassistant/components/bmw_connected_drive/notify.py index 14f6c94dff6..b48441ae5fe 100644 --- a/homeassistant/components/bmw_connected_drive/notify.py +++ b/homeassistant/components/bmw_connected_drive/notify.py @@ -56,7 +56,7 @@ class BMWNotificationService(BaseNotificationService): """Set up the notification service.""" self.targets: dict[str, MyBMWVehicle] = targets - def send_message(self, message: str = "", **kwargs: Any) -> None: + async def async_send_message(self, message: str = "", **kwargs: Any) -> None: """Send a message or POI to the car.""" for vehicle in kwargs[ATTR_TARGET]: vehicle = cast(MyBMWVehicle, vehicle) @@ -81,6 +81,6 @@ class BMWNotificationService(BaseNotificationService): } ) - vehicle.remote_services.trigger_send_poi(location_dict) + await vehicle.remote_services.trigger_send_poi(location_dict) else: raise ValueError(f"'data.{ATTR_LOCATION}' is required.") From fdde4d540d5bd0522ba5d2b2235649032132a97d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 12 Aug 2022 14:04:21 -0400 Subject: [PATCH 10/10] Bumped version to 2022.8.4 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f877b3f34f5..e79c132519d 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "3" +PATCH_VERSION: Final = "4" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) diff --git a/pyproject.toml b/pyproject.toml index 61f6b20af07..6c6b88feb4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.8.3" +version = "2022.8.4" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"