From 753a4e9e5e677a307feac905102297f71825717a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2022 21:43:25 -0500 Subject: [PATCH 01/12] SleepIQ to not retry a re-auth right away --- homeassistant/components/sleepiq/config_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sleepiq/config_flow.py b/homeassistant/components/sleepiq/config_flow.py index 16034b64e8b..77806a1f977 100644 --- a/homeassistant/components/sleepiq/config_flow.py +++ b/homeassistant/components/sleepiq/config_flow.py @@ -85,7 +85,7 @@ class SleepIQFlowHandler(ConfigFlow, domain=DOMAIN): self._reauth_entry = self.hass.config_entries.async_get_entry( self.context["entry_id"] ) - return await self.async_step_reauth_confirm(dict(entry_data)) + return await self.async_step_reauth_confirm() async def async_step_reauth_confirm( self, user_input: dict[str, Any] | None = None From 4452a84ee0b9eaa8c5c9b4b162d6c22a88c8602e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Dec 2022 00:49:57 -1000 Subject: [PATCH 02/12] Bump bluetooth-auto-recovery to 1.0.0 (#83800) fixes https://github.com/home-assistant/core/issues/83673 --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/components/bluetooth/scanner.py | 3 ++- homeassistant/components/bluetooth/util.py | 4 ++-- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 3c926db79d4..4ca4add7fc3 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -9,7 +9,7 @@ "bleak==0.19.2", "bleak-retry-connector==2.10.1", "bluetooth-adapters==0.12.0", - "bluetooth-auto-recovery==0.5.5", + "bluetooth-auto-recovery==1.0.0", "bluetooth-data-tools==0.3.0", "dbus-fast==1.75.0" ], diff --git a/homeassistant/components/bluetooth/scanner.py b/homeassistant/components/bluetooth/scanner.py index 09032715c74..d56c3f76c4c 100644 --- a/homeassistant/components/bluetooth/scanner.py +++ b/homeassistant/components/bluetooth/scanner.py @@ -130,6 +130,7 @@ class HaScanner(BaseHaScanner): new_info_callback: Callable[[BluetoothServiceInfoBleak], None], ) -> None: """Init bluetooth discovery.""" + self.mac_address = address source = address if address != DEFAULT_ADDRESS else adapter or SOURCE_LOCAL super().__init__(hass, source, adapter) self.mode = mode @@ -375,7 +376,7 @@ class HaScanner(BaseHaScanner): # so we log at debug level. If we later come up with a repair # strategy, we will change this to raise a repair issue as well. _LOGGER.debug("%s: adapter stopped responding; executing reset", self.name) - result = await async_reset_adapter(self.adapter) + result = await async_reset_adapter(self.adapter, self.mac_address) _LOGGER.debug("%s: adapter reset result: %s", self.name, result) async def async_stop(self) -> None: diff --git a/homeassistant/components/bluetooth/util.py b/homeassistant/components/bluetooth/util.py index c2336dd7af0..e3f44daff2b 100644 --- a/homeassistant/components/bluetooth/util.py +++ b/homeassistant/components/bluetooth/util.py @@ -36,9 +36,9 @@ def async_load_history_from_system( } -async def async_reset_adapter(adapter: str | None) -> bool | None: +async def async_reset_adapter(adapter: str | None, mac_address: str) -> bool | None: """Reset the adapter.""" if adapter and adapter.startswith("hci"): adapter_id = int(adapter[3:]) - return await recover_adapter(adapter_id) + return await recover_adapter(adapter_id, mac_address) return False diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 6e8f3a511dd..05767d91dc0 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -13,7 +13,7 @@ bcrypt==3.1.7 bleak-retry-connector==2.10.1 bleak==0.19.2 bluetooth-adapters==0.12.0 -bluetooth-auto-recovery==0.5.5 +bluetooth-auto-recovery==1.0.0 bluetooth-data-tools==0.3.0 certifi>=2021.5.30 ciso8601==2.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index 802db40dfd5..bf5b8630216 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -450,7 +450,7 @@ bluemaestro-ble==0.2.0 bluetooth-adapters==0.12.0 # homeassistant.components.bluetooth -bluetooth-auto-recovery==0.5.5 +bluetooth-auto-recovery==1.0.0 # homeassistant.components.bluetooth # homeassistant.components.led_ble diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0fd60298193..6699e7b536d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -364,7 +364,7 @@ bluemaestro-ble==0.2.0 bluetooth-adapters==0.12.0 # homeassistant.components.bluetooth -bluetooth-auto-recovery==0.5.5 +bluetooth-auto-recovery==1.0.0 # homeassistant.components.bluetooth # homeassistant.components.led_ble From 712cb1157f3b2ffbe7210982f996919149434975 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 12 Dec 2022 18:52:47 +0100 Subject: [PATCH 03/12] Update frontend to 20221212.0 (#83842) --- 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 57a31456c3c..e1c12272db4 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -2,7 +2,7 @@ "domain": "frontend", "name": "Home Assistant Frontend", "documentation": "https://www.home-assistant.io/integrations/frontend", - "requirements": ["home-assistant-frontend==20221208.0"], + "requirements": ["home-assistant-frontend==20221212.0"], "dependencies": [ "api", "auth", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 05767d91dc0..8ea2da044d1 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -22,7 +22,7 @@ dbus-fast==1.75.0 fnvhash==0.1.0 hass-nabucasa==0.61.0 home-assistant-bluetooth==1.8.1 -home-assistant-frontend==20221208.0 +home-assistant-frontend==20221212.0 httpx==0.23.1 ifaddr==0.1.7 janus==1.0.0 diff --git a/requirements_all.txt b/requirements_all.txt index bf5b8630216..3e81c5d794e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -884,7 +884,7 @@ hole==0.7.0 holidays==0.17.2 # homeassistant.components.frontend -home-assistant-frontend==20221208.0 +home-assistant-frontend==20221212.0 # homeassistant.components.home_connect homeconnect==0.7.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6699e7b536d..94f662496bb 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -664,7 +664,7 @@ hole==0.7.0 holidays==0.17.2 # homeassistant.components.frontend -home-assistant-frontend==20221208.0 +home-assistant-frontend==20221212.0 # homeassistant.components.home_connect homeconnect==0.7.2 From 3fe2f4f57203dbaf90e4a393bb2181ac22c8a0a9 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 12 Dec 2022 12:33:50 -0500 Subject: [PATCH 04/12] Bump version of ZHA quirks to 0.0.89 (#83848) --- homeassistant/components/zha/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 50a30142bc5..ef5dbb91346 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -7,7 +7,7 @@ "bellows==0.34.5", "pyserial==3.5", "pyserial-asyncio==0.6", - "zha-quirks==0.0.88", + "zha-quirks==0.0.89", "zigpy-deconz==0.19.2", "zigpy==0.52.3", "zigpy-xbee==0.16.2", diff --git a/requirements_all.txt b/requirements_all.txt index 3e81c5d794e..80256ece9e2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2639,7 +2639,7 @@ zengge==0.2 zeroconf==0.39.4 # homeassistant.components.zha -zha-quirks==0.0.88 +zha-quirks==0.0.89 # homeassistant.components.zhong_hong zhong_hong_hvac==1.0.9 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 94f662496bb..497af3994e3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1840,7 +1840,7 @@ zamg==0.1.1 zeroconf==0.39.4 # homeassistant.components.zha -zha-quirks==0.0.88 +zha-quirks==0.0.89 # homeassistant.components.zha zigpy-deconz==0.19.2 From 89efc455e31ddb45e08a1be210354227a2d019cc Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 12 Dec 2022 21:57:12 +0100 Subject: [PATCH 05/12] Bump pychromecast to 13.0.3 (#83861) --- homeassistant/components/cast/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/cast/manifest.json b/homeassistant/components/cast/manifest.json index 00688f642ad..6661614b9cb 100644 --- a/homeassistant/components/cast/manifest.json +++ b/homeassistant/components/cast/manifest.json @@ -3,7 +3,7 @@ "name": "Google Cast", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/cast", - "requirements": ["pychromecast==13.0.2"], + "requirements": ["pychromecast==13.0.3"], "after_dependencies": [ "cloud", "http", diff --git a/requirements_all.txt b/requirements_all.txt index 80256ece9e2..9653e4af335 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1504,7 +1504,7 @@ pycfdns==2.0.1 pychannels==1.2.3 # homeassistant.components.cast -pychromecast==13.0.2 +pychromecast==13.0.3 # homeassistant.components.pocketcasts pycketcasts==1.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 497af3994e3..fce89b7bbad 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1077,7 +1077,7 @@ pybravia==0.2.3 pycfdns==2.0.1 # homeassistant.components.cast -pychromecast==13.0.2 +pychromecast==13.0.3 # homeassistant.components.comfoconnect pycomfoconnect==0.4 From 0a2fa9984d9be7606bdf4c19fea203119c86e705 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Mon, 12 Dec 2022 22:11:57 +0100 Subject: [PATCH 06/12] Move template check into fritzbox entry setup (#83863) * move template check into entry setup * use else in try-except block --- homeassistant/components/fritzbox/__init__.py | 12 +++++++++++- homeassistant/components/fritzbox/coordinator.py | 12 ++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/fritzbox/__init__.py b/homeassistant/components/fritzbox/__init__.py index 40d170db3b3..43bd0bfeeb0 100644 --- a/homeassistant/components/fritzbox/__init__.py +++ b/homeassistant/components/fritzbox/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations from abc import ABC, abstractmethod +from xml.etree.ElementTree import ParseError from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError from pyfritzhome.devicetypes.fritzhomeentitybase import FritzhomeEntityBase @@ -43,7 +44,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: CONF_CONNECTIONS: fritz, } - coordinator = FritzboxDataUpdateCoordinator(hass, entry) + try: + await hass.async_add_executor_job(fritz.update_templates) + except ParseError: + LOGGER.debug("Disable smarthome templates") + has_templates = False + else: + LOGGER.debug("Enable smarthome templates") + has_templates = True + + coordinator = FritzboxDataUpdateCoordinator(hass, entry, has_templates) await coordinator.async_config_entry_first_refresh() diff --git a/homeassistant/components/fritzbox/coordinator.py b/homeassistant/components/fritzbox/coordinator.py index 6bc3bac623f..80087adf9ac 100644 --- a/homeassistant/components/fritzbox/coordinator.py +++ b/homeassistant/components/fritzbox/coordinator.py @@ -3,7 +3,6 @@ from __future__ import annotations from dataclasses import dataclass from datetime import timedelta -from xml.etree.ElementTree import ParseError from pyfritzhome import Fritzhome, FritzhomeDevice, LoginError from pyfritzhome.devicetypes import FritzhomeTemplate @@ -30,17 +29,14 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat configuration_url: str - def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None: + def __init__( + self, hass: HomeAssistant, entry: ConfigEntry, has_templates: bool + ) -> None: """Initialize the Fritzbox Smarthome device coordinator.""" self.entry = entry self.fritz: Fritzhome = hass.data[DOMAIN][self.entry.entry_id][CONF_CONNECTIONS] self.configuration_url = self.fritz.get_prefixed_host() - self.has_templates = True - try: - hass.async_add_executor_job(self.fritz.update_templates) - except ParseError: - LOGGER.info("Disable smarthome templates") - self.has_templates = False + self.has_templates = has_templates super().__init__( hass, From 463edd984beb1255ce9776759b7bf148df028cc0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 12 Dec 2022 16:16:41 -0500 Subject: [PATCH 07/12] Bumped version to 2022.12.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 c99e823ca59..74e090d166e 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -8,7 +8,7 @@ from .backports.enum import StrEnum APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 12 -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 125c7b77e9e..8c8399bf425 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.12.3" +version = "2022.12.4" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From 38ab48b4fd992cb175183d84551fa50fba779f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Wed, 7 Dec 2022 20:02:22 +0100 Subject: [PATCH 08/12] Use the async_migrate_paypal_agreement function to get the migration URL (#83469) * Use the async_migrate_paypal_agreement function to get the migration URL * Update URL * Handle timeout error --- homeassistant/components/cloud/repairs.py | 9 +-- .../components/cloud/subscription.py | 22 +++++++ tests/components/cloud/test_repairs.py | 13 +++- tests/components/cloud/test_subscription.py | 61 +++++++++++++++++++ 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/components/cloud/test_subscription.py diff --git a/homeassistant/components/cloud/repairs.py b/homeassistant/components/cloud/repairs.py index 0d217521c21..bf2df23aca9 100644 --- a/homeassistant/components/cloud/repairs.py +++ b/homeassistant/components/cloud/repairs.py @@ -13,7 +13,7 @@ from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import issue_registry as ir from .const import DOMAIN -from .subscription import async_subscription_info +from .subscription import async_migrate_paypal_agreement, async_subscription_info BACKOFF_TIME = 5 MAX_RETRIES = 60 # This allows for 10 minutes of retries @@ -68,13 +68,13 @@ class LegacySubscriptionRepairFlow(RepairsFlow): async def async_step_change_plan(self, _: None = None) -> FlowResult: """Wait for the user to authorize the app installation.""" + cloud: Cloud = self.hass.data[DOMAIN] + async def _async_wait_for_plan_change() -> None: flow_manager = repairs_flow_manager(self.hass) # We can not get here without a flow manager assert flow_manager is not None - cloud: Cloud = self.hass.data[DOMAIN] - retries = 0 while retries < MAX_RETRIES: self._data = await async_subscription_info(cloud) @@ -90,9 +90,10 @@ class LegacySubscriptionRepairFlow(RepairsFlow): if not self.wait_task: self.wait_task = self.hass.async_create_task(_async_wait_for_plan_change()) + migration = await async_migrate_paypal_agreement(cloud) return self.async_external_step( step_id="change_plan", - url="https://account.nabucasa.com/", + url=migration["url"] if migration else "https://account.nabucasa.com/", ) await self.wait_task diff --git a/homeassistant/components/cloud/subscription.py b/homeassistant/components/cloud/subscription.py index 9a2e5bd87cf..4c18b4f0253 100644 --- a/homeassistant/components/cloud/subscription.py +++ b/homeassistant/components/cloud/subscription.py @@ -1,6 +1,7 @@ """Subscription information.""" from __future__ import annotations +import asyncio import logging from typing import Any @@ -18,7 +19,28 @@ async def async_subscription_info(cloud: Cloud) -> dict[str, Any] | None: try: async with async_timeout.timeout(REQUEST_TIMEOUT): return await cloud_api.async_subscription_info(cloud) + except asyncio.TimeoutError: + _LOGGER.error( + "A timeout of %s was reached while trying to fetch subscription information", + REQUEST_TIMEOUT, + ) except ClientError: _LOGGER.error("Failed to fetch subscription information") return None + + +async def async_migrate_paypal_agreement(cloud: Cloud) -> dict[str, Any] | None: + """Migrate a paypal agreement from legacy.""" + try: + async with async_timeout.timeout(REQUEST_TIMEOUT): + return await cloud_api.async_migrate_paypal_agreement(cloud) + except asyncio.TimeoutError: + _LOGGER.error( + "A timeout of %s was reached while trying to start agreement migration", + REQUEST_TIMEOUT, + ) + except ClientError as exception: + _LOGGER.error("Failed to start agreement migration - %s", exception) + + return None diff --git a/tests/components/cloud/test_repairs.py b/tests/components/cloud/test_repairs.py index 052cdde0d0d..a7f8b2332d7 100644 --- a/tests/components/cloud/test_repairs.py +++ b/tests/components/cloud/test_repairs.py @@ -88,6 +88,10 @@ async def test_legacy_subscription_repair_flow( "https://accounts.nabucasa.com/payments/subscription_info", json={"provider": None}, ) + aioclient_mock.post( + "https://accounts.nabucasa.com/payments/migrate_paypal_agreement", + json={"url": "https://paypal.com"}, + ) cloud_repairs.async_manage_legacy_subscription_issue(hass, {"provider": "legacy"}) repair_issue = issue_registry.async_get_issue( @@ -133,7 +137,7 @@ async def test_legacy_subscription_repair_flow( "flow_id": flow_id, "handler": DOMAIN, "step_id": "change_plan", - "url": "https://account.nabucasa.com/", + "url": "https://paypal.com", "description_placeholders": None, } @@ -161,8 +165,15 @@ async def test_legacy_subscription_repair_flow( async def test_legacy_subscription_repair_flow_timeout( hass: HomeAssistant, hass_client: Callable[..., Awaitable[ClientSession]], + mock_auth: Generator[None, AsyncMock, None], + aioclient_mock: AiohttpClientMocker, ): """Test timeout flow of the fix flow for legacy subscription.""" + aioclient_mock.post( + "https://accounts.nabucasa.com/payments/migrate_paypal_agreement", + status=403, + ) + issue_registry: ir.IssueRegistry = ir.async_get(hass) cloud_repairs.async_manage_legacy_subscription_issue(hass, {"provider": "legacy"}) diff --git a/tests/components/cloud/test_subscription.py b/tests/components/cloud/test_subscription.py new file mode 100644 index 00000000000..4dac93e92a3 --- /dev/null +++ b/tests/components/cloud/test_subscription.py @@ -0,0 +1,61 @@ +"""Test cloud subscription functions.""" +import asyncio +from unittest.mock import AsyncMock, Mock + +from hass_nabucasa import Cloud +import pytest + +from homeassistant.components.cloud.subscription import ( + async_migrate_paypal_agreement, + async_subscription_info, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +from tests.test_util.aiohttp import AiohttpClientMocker + + +@pytest.fixture(name="mocked_cloud") +def mocked_cloud_object(hass: HomeAssistant) -> Cloud: + """Mock cloud object.""" + return Mock( + accounts_server="accounts.nabucasa.com", + auth=Mock(async_check_token=AsyncMock()), + websession=async_get_clientsession(hass), + ) + + +async def test_fetching_subscription_with_timeout_error( + aioclient_mock: AiohttpClientMocker, + caplog: pytest.LogCaptureFixture, + mocked_cloud: Cloud, +): + """Test that we handle timeout error.""" + aioclient_mock.get( + "https://accounts.nabucasa.com/payments/subscription_info", + exc=asyncio.TimeoutError(), + ) + + assert await async_subscription_info(mocked_cloud) is None + assert ( + "A timeout of 10 was reached while trying to fetch subscription information" + in caplog.text + ) + + +async def test_migrate_paypal_agreement_with_timeout_error( + aioclient_mock: AiohttpClientMocker, + caplog: pytest.LogCaptureFixture, + mocked_cloud: Cloud, +): + """Test that we handle timeout error.""" + aioclient_mock.post( + "https://accounts.nabucasa.com/payments/migrate_paypal_agreement", + exc=asyncio.TimeoutError(), + ) + + assert await async_migrate_paypal_agreement(mocked_cloud) is None + assert ( + "A timeout of 10 was reached while trying to start agreement migration" + in caplog.text + ) From 4c2975ad993973fcc9384479cfdf645f44d5671f Mon Sep 17 00:00:00 2001 From: Nyro Date: Tue, 13 Dec 2022 00:08:10 +0100 Subject: [PATCH 09/12] Fix issue on Overkiz Domestic Hot water heater entities with away mode (#83684) * Don't call set boostMode Duration with 0 to disable boost mode * use states.get() instead of states[] * Revert select states --- .../domestic_hot_water_production.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/overkiz/water_heater_entities/domestic_hot_water_production.py b/homeassistant/components/overkiz/water_heater_entities/domestic_hot_water_production.py index 49524e19373..2a8d93bf8eb 100644 --- a/homeassistant/components/overkiz/water_heater_entities/domestic_hot_water_production.py +++ b/homeassistant/components/overkiz/water_heater_entities/domestic_hot_water_production.py @@ -305,14 +305,6 @@ class DomesticHotWaterProduction(OverkizEntity, WaterHeaterEntity): OverkizCommand.SET_BOOST_MODE, OverkizCommand.OFF ) - if self.executor.has_command(OverkizCommand.SET_BOOST_MODE_DURATION): - await self.executor.async_execute_command( - OverkizCommand.SET_BOOST_MODE_DURATION, 0 - ) - await self.executor.async_execute_command( - OverkizCommand.REFRESH_BOOST_MODE_DURATION - ) - if self.executor.has_command(OverkizCommand.SET_CURRENT_OPERATING_MODE): current_operating_mode = self.executor.select_state( OverkizState.CORE_OPERATING_MODE @@ -331,5 +323,10 @@ class DomesticHotWaterProduction(OverkizEntity, WaterHeaterEntity): OverkizCommand.SET_DHW_MODE, self.overkiz_to_operation_mode[operation_mode] ) + if self.executor.has_command(OverkizCommand.REFRESH_BOOST_MODE_DURATION): + await self.executor.async_execute_command( + OverkizCommand.REFRESH_BOOST_MODE_DURATION + ) + if self.executor.has_command(OverkizCommand.REFRESH_DHW_MODE): await self.executor.async_execute_command(OverkizCommand.REFRESH_DHW_MODE) From a3fb8a65148d3b787370f3aa1e3944e2f38b66b4 Mon Sep 17 00:00:00 2001 From: Nyro Date: Tue, 13 Dec 2022 00:17:05 +0100 Subject: [PATCH 10/12] Bump pyoverkiz to 1.7.2 (#83866) Bump pyoverkiz --- homeassistant/components/overkiz/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/overkiz/manifest.json b/homeassistant/components/overkiz/manifest.json index 49a65b78c06..864c34714aa 100644 --- a/homeassistant/components/overkiz/manifest.json +++ b/homeassistant/components/overkiz/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "integration_type": "hub", "documentation": "https://www.home-assistant.io/integrations/overkiz", - "requirements": ["pyoverkiz==1.7.1"], + "requirements": ["pyoverkiz==1.7.2"], "zeroconf": [ { "type": "_kizbox._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index 9653e4af335..c0ccabfc900 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1812,7 +1812,7 @@ pyotgw==2.1.3 pyotp==2.7.0 # homeassistant.components.overkiz -pyoverkiz==1.7.1 +pyoverkiz==1.7.2 # homeassistant.components.openweathermap pyowm==3.2.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fce89b7bbad..517ad04614a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1289,7 +1289,7 @@ pyotgw==2.1.3 pyotp==2.7.0 # homeassistant.components.overkiz -pyoverkiz==1.7.1 +pyoverkiz==1.7.2 # homeassistant.components.openweathermap pyowm==3.2.0 From 8fb400e7ca8b71b328e83c7482822db666edd61b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Dec 2022 16:29:39 -1000 Subject: [PATCH 11/12] Fix bleak-retry-connector get_device hang with HAOS 9.4 and only proxies (#83879) The bleak connection setup to dbus hangs forever instead of errors if there are no local bluetooth adapters and we are using remote proxies. The library now times out when this happens instead of hanging forever. changelog: https://github.com/Bluetooth-Devices/bleak-retry-connector/compare/v2.10.1...v2.10.2 --- homeassistant/components/bluetooth/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/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 4ca4add7fc3..069bb64011d 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -7,7 +7,7 @@ "quality_scale": "internal", "requirements": [ "bleak==0.19.2", - "bleak-retry-connector==2.10.1", + "bleak-retry-connector==2.10.2", "bluetooth-adapters==0.12.0", "bluetooth-auto-recovery==1.0.0", "bluetooth-data-tools==0.3.0", diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 8ea2da044d1..f9c4c4dd2f6 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,7 +10,7 @@ atomicwrites-homeassistant==1.4.1 attrs==21.2.0 awesomeversion==22.9.0 bcrypt==3.1.7 -bleak-retry-connector==2.10.1 +bleak-retry-connector==2.10.2 bleak==0.19.2 bluetooth-adapters==0.12.0 bluetooth-auto-recovery==1.0.0 diff --git a/requirements_all.txt b/requirements_all.txt index c0ccabfc900..b088ec3104a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -422,7 +422,7 @@ bimmer_connected==0.10.4 bizkaibus==0.1.1 # homeassistant.components.bluetooth -bleak-retry-connector==2.10.1 +bleak-retry-connector==2.10.2 # homeassistant.components.bluetooth bleak==0.19.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 517ad04614a..3f857e1839b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -346,7 +346,7 @@ bellows==0.34.5 bimmer_connected==0.10.4 # homeassistant.components.bluetooth -bleak-retry-connector==2.10.1 +bleak-retry-connector==2.10.2 # homeassistant.components.bluetooth bleak==0.19.2 From 31d0e5e316a52bfc4a7bac536eba950e493309a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Dec 2022 16:29:06 -1000 Subject: [PATCH 12/12] Fix HomeKit media players when entity has duplicate sources (#83890) fixes #83852 fixes #83698 --- .../components/homekit/type_remotes.py | 21 +++++++-- .../homekit/test_type_media_players.py | 45 +++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/type_remotes.py b/homeassistant/components/homekit/type_remotes.py index fb808eff8b0..9cc90a6cc28 100644 --- a/homeassistant/components/homekit/type_remotes.py +++ b/homeassistant/components/homekit/type_remotes.py @@ -18,7 +18,7 @@ from homeassistant.const import ( SERVICE_TURN_ON, STATE_ON, ) -from homeassistant.core import callback +from homeassistant.core import State, callback from .accessories import TYPES, HomeAccessory from .const import ( @@ -96,7 +96,7 @@ class RemoteInputSelectAccessory(HomeAccessory): self.sources = [] self.support_select_source = False if features & required_feature: - sources = state.attributes.get(source_list_key, []) + sources = self._get_ordered_source_list_from_state(state) if len(sources) > MAXIMUM_SOURCES: _LOGGER.warning( "%s: Reached maximum number of sources (%s)", @@ -143,6 +143,21 @@ class RemoteInputSelectAccessory(HomeAccessory): serv_input.configure_char(CHAR_CURRENT_VISIBILITY_STATE, value=False) _LOGGER.debug("%s: Added source %s", self.entity_id, source) + def _get_ordered_source_list_from_state(self, state: State) -> list[str]: + """Return ordered source list while preserving order with duplicates removed. + + Some integrations have duplicate sources in the source list + which will make the source list conflict as HomeKit requires + unique source names. + """ + seen = set() + sources: list[str] = [] + for source in state.attributes.get(self.source_list_key, []): + if source not in seen: + sources.append(source) + seen.add(source) + return sources + @abstractmethod def set_on_off(self, value): """Move switch state to value if call came from HomeKit.""" @@ -169,7 +184,7 @@ class RemoteInputSelectAccessory(HomeAccessory): self.char_input_source.set_value(index) return - possible_sources = new_state.attributes.get(self.source_list_key, []) + possible_sources = self._get_ordered_source_list_from_state(new_state) if source in possible_sources: index = possible_sources.index(source) if index >= MAXIMUM_SOURCES: diff --git a/tests/components/homekit/test_type_media_players.py b/tests/components/homekit/test_type_media_players.py index 30b9bc77f5d..e815a25ee7d 100644 --- a/tests/components/homekit/test_type_media_players.py +++ b/tests/components/homekit/test_type_media_players.py @@ -512,3 +512,48 @@ async def test_media_player_television_max_sources(hass, hk_driver, events, capl ) await hass.async_block_till_done() assert acc.char_input_source.value == 0 + + +async def test_media_player_television_duplicate_sources( + hass, hk_driver, events, caplog +): + """Test if television accessory with duplicate sources.""" + entity_id = "media_player.television" + sources = ["MUSIC", "HDMI", "SCREEN MIRRORING", "HDMI", "MUSIC"] + hass.states.async_set( + entity_id, + None, + { + ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV, + ATTR_SUPPORTED_FEATURES: 3469, + ATTR_MEDIA_VOLUME_MUTED: False, + ATTR_INPUT_SOURCE: "HDMI", + ATTR_INPUT_SOURCE_LIST: sources, + }, + ) + await hass.async_block_till_done() + acc = TelevisionMediaPlayer(hass, hk_driver, "MediaPlayer", entity_id, 2, None) + await acc.run() + await hass.async_block_till_done() + + assert acc.aid == 2 + assert acc.category == 31 # Television + + assert acc.char_active.value == 0 + assert acc.char_remote_key.value == 0 + assert acc.char_input_source.value == 1 + assert acc.char_mute.value is False + + hass.states.async_set( + entity_id, + None, + { + ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV, + ATTR_SUPPORTED_FEATURES: 3469, + ATTR_MEDIA_VOLUME_MUTED: False, + ATTR_INPUT_SOURCE: "MUSIC", + ATTR_INPUT_SOURCE_LIST: sources, + }, + ) + await hass.async_block_till_done() + assert acc.char_input_source.value == 0