From 7f79b26341f3bdefbf921299841b8ef96ee96a81 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Mon, 7 Oct 2024 18:15:25 +1000 Subject: [PATCH 01/89] Fix Island status in Teslemetry (#127504) --- homeassistant/components/teslemetry/sensor.py | 12 +- .../components/teslemetry/strings.json | 10 ++ .../teslemetry/snapshots/test_sensor.ambr | 144 ++++++++++-------- 3 files changed, 104 insertions(+), 62 deletions(-) diff --git a/homeassistant/components/teslemetry/sensor.py b/homeassistant/components/teslemetry/sensor.py index 1a6eb0fb8c8..ba7d930fcd0 100644 --- a/homeassistant/components/teslemetry/sensor.py +++ b/homeassistant/components/teslemetry/sensor.py @@ -378,7 +378,17 @@ ENERGY_LIVE_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = ( device_class=SensorDeviceClass.POWER, entity_registry_enabled_default=False, ), - SensorEntityDescription(key="island_status", device_class=SensorDeviceClass.ENUM), + SensorEntityDescription( + key="island_status", + device_class=SensorDeviceClass.ENUM, + options=[ + "on_grid", + "off_grid", + "off_grid_intentional", + "off_grid_unintentional", + "island_status_unknown", + ], + ), ) WALL_CONNECTOR_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = ( diff --git a/homeassistant/components/teslemetry/strings.json b/homeassistant/components/teslemetry/strings.json index b7ba06fbce4..9c3fc09b07b 100644 --- a/homeassistant/components/teslemetry/strings.json +++ b/homeassistant/components/teslemetry/strings.json @@ -392,6 +392,16 @@ "grid_services_power": { "name": "Grid services power" }, + "island_status": { + "name": "Island status", + "state": { + "island_status_unknown": "Unknown", + "on_grid": "On grid", + "off_grid": "Off grid", + "off_grid_intentional": "Off grid intentional", + "off_grid_unintentional": "Off grid unintentional" + } + }, "load_power": { "name": "Load power" }, diff --git a/tests/components/teslemetry/snapshots/test_sensor.ambr b/tests/components/teslemetry/snapshots/test_sensor.ambr index 36ce65b2c89..96cebc2b01f 100644 --- a/tests/components/teslemetry/snapshots/test_sensor.ambr +++ b/tests/components/teslemetry/snapshots/test_sensor.ambr @@ -1751,6 +1751,89 @@ 'state': '0.074', }) # --- +# name: test_sensors[sensor.energy_site_island_status-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'on_grid', + 'off_grid', + 'off_grid_intentional', + 'off_grid_unintentional', + 'island_status_unknown', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.energy_site_island_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Island status', + 'platform': 'teslemetry', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'island_status', + 'unique_id': '123456-island_status', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensors[sensor.energy_site_island_status-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Energy Site Island status', + 'options': list([ + 'on_grid', + 'off_grid', + 'off_grid_intentional', + 'off_grid_unintentional', + 'island_status_unknown', + ]), + }), + 'context': , + 'entity_id': 'sensor.energy_site_island_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on_grid', + }) +# --- +# name: test_sensors[sensor.energy_site_island_status-statealt] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Energy Site Island status', + 'options': list([ + 'on_grid', + 'off_grid', + 'off_grid_intentional', + 'off_grid_unintentional', + 'island_status_unknown', + ]), + }), + 'context': , + 'entity_id': 'sensor.energy_site_island_status', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on_grid', + }) +# --- # name: test_sensors[sensor.energy_site_load_power-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -1824,67 +1907,6 @@ 'state': '6.245', }) # --- -# name: test_sensors[sensor.energy_site_none-entry] - EntityRegistryEntrySnapshot({ - 'aliases': set({ - }), - 'area_id': None, - 'capabilities': None, - 'config_entry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'sensor', - 'entity_category': None, - 'entity_id': 'sensor.energy_site_none', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'options': dict({ - }), - 'original_device_class': , - 'original_icon': None, - 'original_name': None, - 'platform': 'teslemetry', - 'previous_unique_id': None, - 'supported_features': 0, - 'translation_key': 'island_status', - 'unique_id': '123456-island_status', - 'unit_of_measurement': None, - }) -# --- -# name: test_sensors[sensor.energy_site_none-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Energy Site None', - }), - 'context': , - 'entity_id': 'sensor.energy_site_none', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': 'on_grid', - }) -# --- -# name: test_sensors[sensor.energy_site_none-statealt] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'enum', - 'friendly_name': 'Energy Site None', - }), - 'context': , - 'entity_id': 'sensor.energy_site_none', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': 'on_grid', - }) -# --- # name: test_sensors[sensor.energy_site_percentage_charged-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ From df53e19edafb161eb0986685482650c5e65937c5 Mon Sep 17 00:00:00 2001 From: Louis Christ Date: Sat, 5 Oct 2024 19:14:57 +0200 Subject: [PATCH 02/89] Bump pyblu to 1.0.3 (#127571) --- homeassistant/components/bluesound/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bluesound/manifest.json b/homeassistant/components/bluesound/manifest.json index 53f2d8a0240..4d92a5f7fc0 100644 --- a/homeassistant/components/bluesound/manifest.json +++ b/homeassistant/components/bluesound/manifest.json @@ -6,7 +6,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/bluesound", "iot_class": "local_polling", - "requirements": ["pyblu==1.0.2"], + "requirements": ["pyblu==1.0.3"], "zeroconf": [ { "type": "_musc._tcp.local." diff --git a/requirements_all.txt b/requirements_all.txt index 2563b7a1eb9..728fe182de7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1780,7 +1780,7 @@ pybbox==0.0.5-alpha pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==1.0.2 +pyblu==1.0.3 # homeassistant.components.neato pybotvac==0.0.25 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index bee8274ca60..8d74af6391a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1448,7 +1448,7 @@ pybalboa==1.0.2 pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==1.0.2 +pyblu==1.0.3 # homeassistant.components.neato pybotvac==0.0.25 From 2cf898afccf62cdfe01a4c76afe09100cdb1d4bd Mon Sep 17 00:00:00 2001 From: Noah Husby <32528627+noahhusby@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:19:22 -0400 Subject: [PATCH 03/89] Bump aiostreammagic to 2.5.0 (#127595) --- homeassistant/components/cambridge_audio/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/cambridge_audio/manifest.json b/homeassistant/components/cambridge_audio/manifest.json index f2f067a4a9d..232e3d8e2aa 100644 --- a/homeassistant/components/cambridge_audio/manifest.json +++ b/homeassistant/components/cambridge_audio/manifest.json @@ -7,6 +7,6 @@ "integration_type": "device", "iot_class": "local_push", "loggers": ["aiostreammagic"], - "requirements": ["aiostreammagic==2.3.1"], + "requirements": ["aiostreammagic==2.5.0"], "zeroconf": ["_stream-magic._tcp.local.", "_smoip._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 728fe182de7..b40483fa5cb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -380,7 +380,7 @@ aiosolaredge==0.2.0 aiosteamist==1.0.0 # homeassistant.components.cambridge_audio -aiostreammagic==2.3.1 +aiostreammagic==2.5.0 # homeassistant.components.switcher_kis aioswitcher==4.0.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8d74af6391a..2ba898f5367 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -362,7 +362,7 @@ aiosolaredge==0.2.0 aiosteamist==1.0.0 # homeassistant.components.cambridge_audio -aiostreammagic==2.3.1 +aiostreammagic==2.5.0 # homeassistant.components.switcher_kis aioswitcher==4.0.3 From 1184ee4a5982a2f47b51fbb9f26cd0cceba7d917 Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 4 Oct 2024 22:07:51 -0700 Subject: [PATCH 04/89] Bump opower to 0.8.2 (#127598) * Bump opower to 0.8.1 to fix enmax * Update manifest.json * Update requirements_all.txt * Update requirements_test_all.txt --- homeassistant/components/opower/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opower/manifest.json b/homeassistant/components/opower/manifest.json index c347e52ef0e..23386a777d2 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", "loggers": ["opower"], - "requirements": ["opower==0.8.0"] + "requirements": ["opower==0.8.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index b40483fa5cb..581b8e97e9b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1544,7 +1544,7 @@ openwrt-luci-rpc==1.1.17 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.8.0 +opower==0.8.2 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2ba898f5367..b8663e45918 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1274,7 +1274,7 @@ openhomedevice==2.2.0 openwebifpy==4.2.7 # homeassistant.components.opower -opower==0.8.0 +opower==0.8.2 # homeassistant.components.oralb oralb-ble==0.17.6 From b902cb5a13e4408e0187be6e2be4e82a4108383c Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Sat, 5 Oct 2024 20:04:10 +1000 Subject: [PATCH 05/89] Fix wake up in Tesla Fleet (#127615) --- homeassistant/components/tesla_fleet/button.py | 5 +++-- tests/components/tesla_fleet/test_button.py | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tesla_fleet/button.py b/homeassistant/components/tesla_fleet/button.py index 548bf065397..87cd95576d2 100644 --- a/homeassistant/components/tesla_fleet/button.py +++ b/homeassistant/components/tesla_fleet/button.py @@ -20,8 +20,9 @@ from .models import TeslaFleetVehicleData PARALLEL_UPDATES = 0 -async def do_nothing() -> None: - """Do nothing.""" +async def do_nothing() -> dict[str, dict[str, bool]]: + """Do nothing with a positive result.""" + return {"response": {"result": True}} @dataclass(frozen=True, kw_only=True) diff --git a/tests/components/tesla_fleet/test_button.py b/tests/components/tesla_fleet/test_button.py index 8b83011e6f4..addba00b93d 100644 --- a/tests/components/tesla_fleet/test_button.py +++ b/tests/components/tesla_fleet/test_button.py @@ -28,6 +28,13 @@ async def test_button( await setup_platform(hass, normal_config_entry, [Platform.BUTTON]) assert_entities(hass, normal_config_entry.entry_id, entity_registry, snapshot) + await hass.services.async_call( + BUTTON_DOMAIN, + SERVICE_PRESS, + {ATTR_ENTITY_ID: ["button.test_wake"]}, + blocking=True, + ) + @pytest.mark.parametrize( ("name", "func"), From d1eda9dd73141243b214bf8154dfe80cc3308009 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Sat, 5 Oct 2024 03:05:11 -0700 Subject: [PATCH 06/89] Update Radarr config flow to standardize ports (#127620) --- homeassistant/components/radarr/config_flow.py | 7 +++++++ tests/components/radarr/test_config_flow.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/homeassistant/components/radarr/config_flow.py b/homeassistant/components/radarr/config_flow.py index c748c63e992..ab32a5d7352 100644 --- a/homeassistant/components/radarr/config_flow.py +++ b/homeassistant/components/radarr/config_flow.py @@ -10,6 +10,7 @@ from aiopyarr import exceptions from aiopyarr.models.host_configuration import PyArrHostConfiguration from aiopyarr.radarr_client import RadarrClient import voluptuous as vol +from yarl import URL from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.const import CONF_API_KEY, CONF_URL, CONF_VERIFY_SSL @@ -54,6 +55,12 @@ class RadarrConfigFlow(ConfigFlow, domain=DOMAIN): user_input = dict(self.entry.data) if self.entry else None else: + # aiopyarr defaults to the service port if one isn't given + # this is counter to standard practice where http = 80 + # and https = 443. + url = URL(user_input[CONF_URL]) + user_input[CONF_URL] = f"{url.scheme}://{url.host}:{url.port}{url.path}" + try: if result := await validate_input(self.hass, user_input): user_input[CONF_API_KEY] = result[1] diff --git a/tests/components/radarr/test_config_flow.py b/tests/components/radarr/test_config_flow.py index 0ff93536957..096c78e1c4a 100644 --- a/tests/components/radarr/test_config_flow.py +++ b/tests/components/radarr/test_config_flow.py @@ -137,6 +137,23 @@ async def test_zero_conf(hass: HomeAssistant) -> None: assert result["data"] == CONF_DATA +async def test_url_rewrite(hass: HomeAssistant) -> None: + """Test auth flow url rewrite.""" + with patch( + "homeassistant.components.radarr.config_flow.RadarrClient.async_try_zeroconf", + return_value=("v3", API_KEY, "/test"), + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={CONF_SOURCE: SOURCE_USER}, + data={CONF_URL: "https://192.168.1.100/test", CONF_VERIFY_SSL: False}, + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == DEFAULT_NAME + assert result["data"][CONF_URL] == "https://192.168.1.100:443/test" + + @pytest.mark.freeze_time("2021-12-03 00:00:00+00:00") async def test_full_reauth_flow_implementation( hass: HomeAssistant, aioclient_mock: AiohttpClientMocker From be2b5a4c3a80ccf8b02f41e7f530a6baf22325c9 Mon Sep 17 00:00:00 2001 From: dontinelli <73341522+dontinelli@users.noreply.github.com> Date: Sun, 6 Oct 2024 10:03:16 +0200 Subject: [PATCH 07/89] Bump fyta_cli to 0.6.7 (#127650) --- homeassistant/components/fyta/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/fyta/manifest.json b/homeassistant/components/fyta/manifest.json index dbd44ed34dc..73f6b42f53b 100644 --- a/homeassistant/components/fyta/manifest.json +++ b/homeassistant/components/fyta/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["fyta_cli==0.6.6"] + "requirements": ["fyta_cli==0.6.7"] } diff --git a/requirements_all.txt b/requirements_all.txt index 581b8e97e9b..ceaca0d9ef8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -933,7 +933,7 @@ freesms==0.2.0 fritzconnection[qr]==1.13.2 # homeassistant.components.fyta -fyta_cli==0.6.6 +fyta_cli==0.6.7 # homeassistant.components.google_translate gTTS==2.2.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b8663e45918..fcb21778c5a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -786,7 +786,7 @@ freebox-api==1.1.0 fritzconnection[qr]==1.13.2 # homeassistant.components.fyta -fyta_cli==0.6.6 +fyta_cli==0.6.7 # homeassistant.components.google_translate gTTS==2.2.4 From 327cb70bb8dbee5f11c40ec75e56311d715dcb92 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sun, 6 Oct 2024 00:46:50 +0200 Subject: [PATCH 08/89] Revert "Fix enum lookup (#125220)" (#127680) This reverts commit 1bc63a61be8057850f68e0ff4e0c94563d5a41c9. --- homeassistant/components/google_cloud/tts.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/google_cloud/tts.py b/homeassistant/components/google_cloud/tts.py index e7bb899361a..c3a8254ad90 100644 --- a/homeassistant/components/google_cloud/tts.py +++ b/homeassistant/components/google_cloud/tts.py @@ -172,10 +172,12 @@ class BaseGoogleCloudProvider: _LOGGER.error("Error: %s when validating options: %s", err, options) return None, None - encoding = texttospeech.AudioEncoding(options[CONF_ENCODING]) - gender: texttospeech.SsmlVoiceGender | None = texttospeech.SsmlVoiceGender( + encoding: texttospeech.AudioEncoding = texttospeech.AudioEncoding[ + options[CONF_ENCODING] + ] # type: ignore[misc] + gender: texttospeech.SsmlVoiceGender | None = texttospeech.SsmlVoiceGender[ options[CONF_GENDER] - ) + ] # type: ignore[misc] voice = options[CONF_VOICE] if voice: gender = None From be99329efae42cf3117c8fa62cbaf1a88cdf2c34 Mon Sep 17 00:00:00 2001 From: David Knowles Date: Sun, 6 Oct 2024 01:42:39 -0400 Subject: [PATCH 09/89] Fix problems with automatic management of Schlage locks (#127689) Use the correct identifiers for existing lock devices --- .../components/schlage/coordinator.py | 14 +++++++++--- tests/components/schlage/test_init.py | 22 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/schlage/coordinator.py b/homeassistant/components/schlage/coordinator.py index 365fabb8ac7..53bb43751a9 100644 --- a/homeassistant/components/schlage/coordinator.py +++ b/homeassistant/components/schlage/coordinator.py @@ -90,13 +90,21 @@ class SchlageDataUpdateCoordinator(DataUpdateCoordinator[SchlageData]): devices = dr.async_entries_for_config_entry( device_registry, self.config_entry.entry_id ) - previous_locks = {device.id for device in devices} + previous_locks = set() + previous_locks_by_lock_id = {} + for device in devices: + for domain, identifier in device.identifiers: + if domain == DOMAIN: + previous_locks.add(identifier) + previous_locks_by_lock_id[identifier] = device + continue current_locks = set(self.data.locks.keys()) + if removed_locks := previous_locks - current_locks: LOGGER.debug("Removed locks: %s", ", ".join(removed_locks)) - for device_id in removed_locks: + for lock_id in removed_locks: device_registry.async_update_device( - device_id=device_id, + device_id=previous_locks_by_lock_id[lock_id].id, remove_config_entry_id=self.config_entry.entry_id, ) diff --git a/tests/components/schlage/test_init.py b/tests/components/schlage/test_init.py index 1f18bdde218..e40fc83a7ac 100644 --- a/tests/components/schlage/test_init.py +++ b/tests/components/schlage/test_init.py @@ -12,6 +12,7 @@ from syrupy.assertion import SnapshotAssertion from homeassistant.components.schlage.const import DOMAIN, UPDATE_INTERVAL from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.core import HomeAssistant +import homeassistant.helpers.device_registry as dr from homeassistant.helpers.device_registry import DeviceRegistry from tests.common import MockConfigEntry, async_fire_time_changed @@ -125,6 +126,10 @@ async def test_auto_add_device( """Test new devices are auto-added to the device registry.""" device = device_registry.async_get_device(identifiers={(DOMAIN, "test")}) assert device is not None + all_devices = dr.async_entries_for_config_entry( + device_registry, mock_added_config_entry.entry_id + ) + assert len(all_devices) == 1 mock_lock_attrs["device_id"] = "test2" new_mock_lock = create_autospec(Lock) @@ -139,19 +144,21 @@ async def test_auto_add_device( new_device = device_registry.async_get_device(identifiers={(DOMAIN, "test2")}) assert new_device is not None + all_devices = dr.async_entries_for_config_entry( + device_registry, mock_added_config_entry.entry_id + ) + assert len(all_devices) == 2 + async def test_auto_remove_device( hass: HomeAssistant, device_registry: DeviceRegistry, mock_added_config_entry: ConfigEntry, mock_schlage: Mock, - mock_lock: Mock, - mock_lock_attrs: dict[str, Any], freezer: FrozenDateTimeFactory, ) -> None: """Test new devices are auto-added to the device registry.""" - device = device_registry.async_get_device(identifiers={(DOMAIN, "test")}) - assert device is not None + assert device_registry.async_get_device(identifiers={(DOMAIN, "test")}) is not None mock_schlage.locks.return_value = [] @@ -160,5 +167,8 @@ async def test_auto_remove_device( async_fire_time_changed(hass) await hass.async_block_till_done(wait_background_tasks=True) - new_device = device_registry.async_get_device(identifiers={(DOMAIN, "test")}) - assert new_device is None + assert device_registry.async_get_device(identifiers={(DOMAIN, "test")}) is None + all_devices = dr.async_entries_for_config_entry( + device_registry, mock_added_config_entry.entry_id + ) + assert len(all_devices) == 0 From 37f611a8d3599516806bb140278db15ad5f76c83 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 6 Oct 2024 19:21:19 +0200 Subject: [PATCH 10/89] Fix typo in HDMI CEC (#127714) --- homeassistant/components/hdmi_cec/strings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/hdmi_cec/strings.json b/homeassistant/components/hdmi_cec/strings.json index 22715907a99..d280cfc1a2b 100644 --- a/homeassistant/components/hdmi_cec/strings.json +++ b/homeassistant/components/hdmi_cec/strings.json @@ -24,11 +24,11 @@ }, "cmd": { "name": "Command", - "description": "Command itself. Could be decimal number or string with hexadeximal notation: \"0x10\"." + "description": "Command itself. Could be decimal number or string with hexadecimal notation: \"0x10\"." }, "dst": { "name": "Destination", - "description": "Destination for command. Could be decimal number or string with hexadeximal notation: \"0x10\"." + "description": "Destination for command. Could be decimal number or string with hexadecimal notation: \"0x10\"." }, "raw": { "name": "Raw", @@ -36,7 +36,7 @@ }, "src": { "name": "Source", - "description": "Source of command. Could be decimal number or string with hexadeximal notation: \"0x10\"." + "description": "Source of command. Could be decimal number or string with hexadecimal notation: \"0x10\"." } } }, From 041d663cb8da4e8dbb4902f66cf5c2be6e149c5b Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 6 Oct 2024 19:21:07 +0200 Subject: [PATCH 11/89] Fix Withings log message (#127716) --- homeassistant/components/withings/sensor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/withings/sensor.py b/homeassistant/components/withings/sensor.py index 20fd72845ae..4c78f82bfe7 100644 --- a/homeassistant/components/withings/sensor.py +++ b/homeassistant/components/withings/sensor.py @@ -802,7 +802,8 @@ async def async_setup_entry( if not entities: LOGGER.warning( - "No data found for Withings entry %s, sensors will be added when new data is available" + "No data found for Withings entry %s, sensors will be added when new data is available", + entry.title, ) async_add_entities(entities) From adf7474edb34adfd6fbbe08b48c9c999e0d1595d Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 6 Oct 2024 22:45:13 +0200 Subject: [PATCH 12/89] Bump NYT Games to 0.4.3 (#127717) --- homeassistant/components/nyt_games/coordinator.py | 2 +- homeassistant/components/nyt_games/manifest.json | 2 +- homeassistant/components/nyt_games/sensor.py | 10 ++++++---- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/nyt_games/coordinator.py b/homeassistant/components/nyt_games/coordinator.py index 3b695574750..5e88a5dd92a 100644 --- a/homeassistant/components/nyt_games/coordinator.py +++ b/homeassistant/components/nyt_games/coordinator.py @@ -23,7 +23,7 @@ class NYTGamesData: wordle: Wordle spelling_bee: SpellingBee | None - connections: Connections + connections: Connections | None class NYTGamesCoordinator(DataUpdateCoordinator[NYTGamesData]): diff --git a/homeassistant/components/nyt_games/manifest.json b/homeassistant/components/nyt_games/manifest.json index 1cdc5988e38..a2cd5629ed1 100644 --- a/homeassistant/components/nyt_games/manifest.json +++ b/homeassistant/components/nyt_games/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/nyt_games", "integration_type": "service", "iot_class": "cloud_polling", - "requirements": ["nyt_games==0.4.2"] + "requirements": ["nyt_games==0.4.3"] } diff --git a/homeassistant/components/nyt_games/sensor.py b/homeassistant/components/nyt_games/sensor.py index 6e19a4c21dc..57759fb354d 100644 --- a/homeassistant/components/nyt_games/sensor.py +++ b/homeassistant/components/nyt_games/sensor.py @@ -161,10 +161,11 @@ async def async_setup_entry( NYTGamesSpellingBeeSensor(coordinator, description) for description in SPELLING_BEE_SENSORS ) - entities.extend( - NYTGamesConnectionsSensor(coordinator, description) - for description in CONNECTIONS_SENSORS - ) + if coordinator.data.connections is not None: + entities.extend( + NYTGamesConnectionsSensor(coordinator, description) + for description in CONNECTIONS_SENSORS + ) async_add_entities(entities) @@ -236,4 +237,5 @@ class NYTGamesConnectionsSensor(ConnectionsEntity, SensorEntity): @property def native_value(self) -> StateType | date: """Return the state of the sensor.""" + assert self.coordinator.data.connections is not None return self.entity_description.value_fn(self.coordinator.data.connections) diff --git a/requirements_all.txt b/requirements_all.txt index ceaca0d9ef8..a7ad2d6e3a4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1484,7 +1484,7 @@ numato-gpio==0.13.0 numpy==1.26.4 # homeassistant.components.nyt_games -nyt_games==0.4.2 +nyt_games==0.4.3 # homeassistant.components.oasa_telematics oasatelematics==0.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fcb21778c5a..56f86b73f54 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1232,7 +1232,7 @@ numato-gpio==0.13.0 numpy==1.26.4 # homeassistant.components.nyt_games -nyt_games==0.4.2 +nyt_games==0.4.3 # homeassistant.components.google oauth2client==4.1.3 From d00e1cb6a590b8f67f0e45592cda6c35860af7fd Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sun, 6 Oct 2024 19:21:48 +0200 Subject: [PATCH 13/89] Bump airgradient to 0.9.1 (#127718) --- homeassistant/components/airgradient/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airgradient/manifest.json b/homeassistant/components/airgradient/manifest.json index c0472131357..13764142697 100644 --- a/homeassistant/components/airgradient/manifest.json +++ b/homeassistant/components/airgradient/manifest.json @@ -6,6 +6,6 @@ "documentation": "https://www.home-assistant.io/integrations/airgradient", "integration_type": "device", "iot_class": "local_polling", - "requirements": ["airgradient==0.9.0"], + "requirements": ["airgradient==0.9.1"], "zeroconf": ["_airgradient._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index a7ad2d6e3a4..e7b3fbb1fff 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -419,7 +419,7 @@ aiowithings==3.0.3 aioymaps==1.2.5 # homeassistant.components.airgradient -airgradient==0.9.0 +airgradient==0.9.1 # homeassistant.components.airly airly==1.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 56f86b73f54..5d80f8fb319 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -401,7 +401,7 @@ aiowithings==3.0.3 aioymaps==1.2.5 # homeassistant.components.airgradient -airgradient==0.9.0 +airgradient==0.9.1 # homeassistant.components.airly airly==1.1.0 From b927763d8d49ab3b2254a5a7f24474d95c0de9c5 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Mon, 7 Oct 2024 08:14:19 +0200 Subject: [PATCH 14/89] Add translation string for Withings wrong account (#127719) --- homeassistant/components/withings/strings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/withings/strings.json b/homeassistant/components/withings/strings.json index fb86b16c3be..b7da59eda4c 100644 --- a/homeassistant/components/withings/strings.json +++ b/homeassistant/components/withings/strings.json @@ -20,7 +20,8 @@ "oauth_error": "[%key:common::config_flow::abort::oauth2_error%]", "oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]", "oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]", - "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]" + "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]", + "wrong_account": "Authenticated account does not match the account to be reauthenticated. Please log in with the correct account." }, "create_entry": { "default": "Successfully authenticated with Withings." From 3b6f88cfa796266c2460913cb941fb094334a1f2 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Mon, 7 Oct 2024 08:43:32 +0200 Subject: [PATCH 15/89] Increase connection timeout in CalDAV (#127727) --- homeassistant/components/caldav/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/caldav/__init__.py b/homeassistant/components/caldav/__init__.py index 3111460e968..beb03cec554 100644 --- a/homeassistant/components/caldav/__init__.py +++ b/homeassistant/components/caldav/__init__.py @@ -34,7 +34,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: username=entry.data[CONF_USERNAME], password=entry.data[CONF_PASSWORD], ssl_verify_cert=entry.data[CONF_VERIFY_SSL], - timeout=10, + timeout=30, ) try: await hass.async_add_executor_job(client.principal) From 1d132d7a1e330fc2bda29903c153d9541b054aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Klomp?= Date: Mon, 7 Oct 2024 08:19:55 +0200 Subject: [PATCH 16/89] Migrate SMA unique id to str (#127732) --- homeassistant/components/sma/__init__.py | 18 ++++++++++++++ homeassistant/components/sma/config_flow.py | 3 ++- tests/components/sma/__init__.py | 2 +- tests/components/sma/conftest.py | 3 ++- tests/components/sma/test_init.py | 27 +++++++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/components/sma/test_init.py diff --git a/homeassistant/components/sma/__init__.py b/homeassistant/components/sma/__init__.py index febd4e34aaf..d8a7929ae79 100644 --- a/homeassistant/components/sma/__init__.py +++ b/homeassistant/components/sma/__init__.py @@ -135,3 +135,21 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: data[PYSMA_REMOVE_LISTENER]() return unload_ok + + +async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Migrate entry.""" + + _LOGGER.debug("Migrating from version %s", entry.version) + + if entry.version == 1: + # 1 -> 2: Unique ID from integer to string + if entry.minor_version == 1: + minor_version = 2 + hass.config_entries.async_update_entry( + entry, unique_id=str(entry.unique_id), minor_version=minor_version + ) + + _LOGGER.debug("Migration successful") + + return True diff --git a/homeassistant/components/sma/config_flow.py b/homeassistant/components/sma/config_flow.py index fe26cbee2c8..4b3e01a79a8 100644 --- a/homeassistant/components/sma/config_flow.py +++ b/homeassistant/components/sma/config_flow.py @@ -40,6 +40,7 @@ class SmaConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for SMA.""" VERSION = 1 + MINOR_VERSION = 2 def __init__(self) -> None: """Initialize.""" @@ -76,7 +77,7 @@ class SmaConfigFlow(ConfigFlow, domain=DOMAIN): errors["base"] = "unknown" if not errors: - await self.async_set_unique_id(device_info["serial"]) + await self.async_set_unique_id(str(device_info["serial"])) self._abort_if_unique_id_configured(updates=self._data) return self.async_create_entry( title=self._data[CONF_HOST], data=self._data diff --git a/tests/components/sma/__init__.py b/tests/components/sma/__init__.py index aefb99cf1b1..80837c718a9 100644 --- a/tests/components/sma/__init__.py +++ b/tests/components/sma/__init__.py @@ -6,7 +6,7 @@ MOCK_DEVICE = { "manufacturer": "SMA", "name": "SMA Device Name", "type": "Sunny Boy 3.6", - "serial": "123456789", + "serial": 123456789, } MOCK_USER_INPUT = { diff --git a/tests/components/sma/conftest.py b/tests/components/sma/conftest.py index a54f478a31d..dd47a0f1055 100644 --- a/tests/components/sma/conftest.py +++ b/tests/components/sma/conftest.py @@ -22,9 +22,10 @@ def mock_config_entry() -> MockConfigEntry: return MockConfigEntry( domain=DOMAIN, title=MOCK_DEVICE["name"], - unique_id=MOCK_DEVICE["serial"], + unique_id=str(MOCK_DEVICE["serial"]), data=MOCK_USER_INPUT, source=config_entries.SOURCE_IMPORT, + minor_version=2, ) diff --git a/tests/components/sma/test_init.py b/tests/components/sma/test_init.py new file mode 100644 index 00000000000..0cc82f49a41 --- /dev/null +++ b/tests/components/sma/test_init.py @@ -0,0 +1,27 @@ +"""Test the sma init file.""" + +from homeassistant.components.sma.const import DOMAIN +from homeassistant.config_entries import SOURCE_IMPORT +from homeassistant.core import HomeAssistant + +from . import MOCK_DEVICE, MOCK_USER_INPUT, _patch_async_setup_entry + +from tests.common import MockConfigEntry + + +async def test_migrate_entry_minor_version_1_2(hass: HomeAssistant) -> None: + """Test migrating a 1.1 config entry to 1.2.""" + with _patch_async_setup_entry(): + entry = MockConfigEntry( + domain=DOMAIN, + title=MOCK_DEVICE["name"], + unique_id=MOCK_DEVICE["serial"], # Not converted to str + data=MOCK_USER_INPUT, + source=SOURCE_IMPORT, + minor_version=1, + ) + entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(entry.entry_id) + assert entry.version == 1 + assert entry.minor_version == 2 + assert entry.unique_id == str(MOCK_DEVICE["serial"]) From 31a075fb135d2bf7b9450fce32e25c85ad993f0f Mon Sep 17 00:00:00 2001 From: Raj Laud <50647620+rajlaud@users.noreply.github.com> Date: Fri, 11 Oct 2024 07:39:33 -0400 Subject: [PATCH 17/89] Remove stale references in squeezebox services.yaml (#127739) --- homeassistant/components/squeezebox/icons.json | 6 ------ .../components/squeezebox/services.yaml | 16 ---------------- homeassistant/components/squeezebox/strings.json | 14 -------------- 3 files changed, 36 deletions(-) diff --git a/homeassistant/components/squeezebox/icons.json b/homeassistant/components/squeezebox/icons.json index e86016329f5..29911ddad77 100644 --- a/homeassistant/components/squeezebox/icons.json +++ b/homeassistant/components/squeezebox/icons.json @@ -27,12 +27,6 @@ }, "call_query": { "service": "mdi:database" - }, - "sync": { - "service": "mdi:sync" - }, - "unsync": { - "service": "mdi:sync-off" } } } diff --git a/homeassistant/components/squeezebox/services.yaml b/homeassistant/components/squeezebox/services.yaml index 90f9bf2d769..07885ae5dd6 100644 --- a/homeassistant/components/squeezebox/services.yaml +++ b/homeassistant/components/squeezebox/services.yaml @@ -30,19 +30,3 @@ call_query: advanced: true selector: object: -sync: - target: - entity: - integration: squeezebox - domain: media_player - fields: - other_player: - required: true - example: "media_player.living_room" - selector: - text: -unsync: - target: - entity: - integration: squeezebox - domain: media_player diff --git a/homeassistant/components/squeezebox/strings.json b/homeassistant/components/squeezebox/strings.json index 1a120ee0567..b1b71cd8c1d 100644 --- a/homeassistant/components/squeezebox/strings.json +++ b/homeassistant/components/squeezebox/strings.json @@ -60,20 +60,6 @@ "description": "[%key:component::squeezebox::services::call_method::fields::parameters::description%]" } } - }, - "sync": { - "name": "Sync", - "description": "Adds another player to this player's sync group. If the other player is already in a sync group, it will leave it.\n.", - "fields": { - "other_player": { - "name": "Other player", - "description": "Name of the other Squeezebox player to link." - } - } - }, - "unsync": { - "name": "Unsync", - "description": "Removes this player from its sync group." } }, "entity": { From 2c99fdc0926471db75c139d6c3553e1da3938bcd Mon Sep 17 00:00:00 2001 From: Johan Gustafsson Date: Sun, 6 Oct 2024 17:33:54 +0200 Subject: [PATCH 18/89] Fix Aurora integration casts longitude and latitude to integer (#127740) Fix Aurora integration casts longitude and latitude to integer (#100817) --- homeassistant/components/aurora/coordinator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/aurora/coordinator.py b/homeassistant/components/aurora/coordinator.py index 422dff83922..9771cc53652 100644 --- a/homeassistant/components/aurora/coordinator.py +++ b/homeassistant/components/aurora/coordinator.py @@ -38,8 +38,8 @@ class AuroraDataUpdateCoordinator(DataUpdateCoordinator[int]): ) self.api = AuroraForecast(async_get_clientsession(hass)) - self.latitude = int(self.config_entry.data[CONF_LATITUDE]) - self.longitude = int(self.config_entry.data[CONF_LONGITUDE]) + self.latitude = round(self.config_entry.data[CONF_LATITUDE]) + self.longitude = round(self.config_entry.data[CONF_LONGITUDE]) self.threshold = int( self.config_entry.options.get(CONF_THRESHOLD, DEFAULT_THRESHOLD) ) From 5da3ca4bb114893e542b6d4f55ca801ed409fb26 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Mon, 7 Oct 2024 08:10:48 +0200 Subject: [PATCH 19/89] Bump python-linkplay to 0.0.15 (#127748) --- homeassistant/components/linkplay/manifest.json | 3 ++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/linkplay/manifest.json b/homeassistant/components/linkplay/manifest.json index 8adae25b0ae..dd1e08eda49 100644 --- a/homeassistant/components/linkplay/manifest.json +++ b/homeassistant/components/linkplay/manifest.json @@ -6,6 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/linkplay", "integration_type": "hub", "iot_class": "local_polling", - "requirements": ["python-linkplay==0.0.12"], + "loggers": ["linkplay"], + "requirements": ["python-linkplay==0.0.15"], "zeroconf": ["_linkplay._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index e7b3fbb1fff..c6068eec4f9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2343,7 +2343,7 @@ python-juicenet==1.1.0 python-kasa[speedups]==0.7.4 # homeassistant.components.linkplay -python-linkplay==0.0.12 +python-linkplay==0.0.15 # homeassistant.components.lirc # python-lirc==1.2.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5d80f8fb319..d11c1647403 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1864,7 +1864,7 @@ python-juicenet==1.1.0 python-kasa[speedups]==0.7.4 # homeassistant.components.linkplay -python-linkplay==0.0.12 +python-linkplay==0.0.15 # homeassistant.components.matter python-matter-server==6.5.2 From 46d9ac8380c0daa9fea8a97e9866095dc020ae4e Mon Sep 17 00:00:00 2001 From: Ricardo Marques Date: Tue, 8 Oct 2024 16:44:59 +0100 Subject: [PATCH 20/89] Fix custom account config flow setup (#127750) --- homeassistant/components/ovo_energy/__init__.py | 4 ++-- homeassistant/components/ovo_energy/config_flow.py | 2 +- tests/components/ovo_energy/test_config_flow.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ovo_energy/__init__.py b/homeassistant/components/ovo_energy/__init__.py index 7cce25d08d5..0576421fa71 100644 --- a/homeassistant/components/ovo_energy/__init__.py +++ b/homeassistant/components/ovo_energy/__init__.py @@ -32,7 +32,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: client_session=async_get_clientsession(hass), ) - if custom_account := entry.data.get(CONF_ACCOUNT) is not None: + if (custom_account := entry.data.get(CONF_ACCOUNT)) is not None: client.custom_account_id = custom_account try: @@ -49,7 +49,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_update_data() -> OVODailyUsage: """Fetch data from OVO Energy.""" - if custom_account := entry.data.get(CONF_ACCOUNT) is not None: + if (custom_account := entry.data.get(CONF_ACCOUNT)) is not None: client.custom_account_id = custom_account async with asyncio.timeout(10): diff --git a/homeassistant/components/ovo_energy/config_flow.py b/homeassistant/components/ovo_energy/config_flow.py index 87d53e5fbf9..e65aae91e0f 100644 --- a/homeassistant/components/ovo_energy/config_flow.py +++ b/homeassistant/components/ovo_energy/config_flow.py @@ -46,7 +46,7 @@ class OVOEnergyFlowHandler(ConfigFlow, domain=DOMAIN): client_session=async_get_clientsession(self.hass), ) - if custom_account := user_input.get(CONF_ACCOUNT) is not None: + if (custom_account := user_input.get(CONF_ACCOUNT)) is not None: client.custom_account_id = custom_account try: diff --git a/tests/components/ovo_energy/test_config_flow.py b/tests/components/ovo_energy/test_config_flow.py index c3f77ca5007..568d97b8d46 100644 --- a/tests/components/ovo_energy/test_config_flow.py +++ b/tests/components/ovo_energy/test_config_flow.py @@ -117,6 +117,7 @@ async def test_full_flow_implementation(hass: HomeAssistant) -> None: assert result2["type"] is FlowResultType.CREATE_ENTRY assert result2["data"][CONF_USERNAME] == FIXTURE_USER_INPUT[CONF_USERNAME] assert result2["data"][CONF_PASSWORD] == FIXTURE_USER_INPUT[CONF_PASSWORD] + assert result2["data"][CONF_ACCOUNT] == FIXTURE_USER_INPUT[CONF_ACCOUNT] async def test_reauth_authorization_error(hass: HomeAssistant) -> None: From bff2d5c26ce9dace70e63eca8c74595622f2c801 Mon Sep 17 00:00:00 2001 From: dontinelli <73341522+dontinelli@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:21:25 +0200 Subject: [PATCH 21/89] Bump solarlog_cli to 0.3.1 (#127753) --- homeassistant/components/solarlog/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/solarlog/manifest.json b/homeassistant/components/solarlog/manifest.json index 99ddc2ed162..274c97c76b5 100644 --- a/homeassistant/components/solarlog/manifest.json +++ b/homeassistant/components/solarlog/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/solarlog", "iot_class": "local_polling", "loggers": ["solarlog_cli"], - "requirements": ["solarlog_cli==0.3.0"] + "requirements": ["solarlog_cli==0.3.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index c6068eec4f9..1cdfc5956e2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2676,7 +2676,7 @@ soco==0.30.4 solaredge-local==0.2.3 # homeassistant.components.solarlog -solarlog_cli==0.3.0 +solarlog_cli==0.3.1 # homeassistant.components.solax solax==3.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d11c1647403..24f9ccb5359 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2122,7 +2122,7 @@ snapcast==2.3.6 soco==0.30.4 # homeassistant.components.solarlog -solarlog_cli==0.3.0 +solarlog_cli==0.3.1 # homeassistant.components.solax solax==3.1.1 From bb9fd126e5008eafbf733b873bcaf30a33f3e8a8 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 27 Sep 2024 20:29:46 +0200 Subject: [PATCH 22/89] Update DoorBirdPy to 3.0.3 (#126949) --- homeassistant/components/doorbird/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/doorbird/manifest.json b/homeassistant/components/doorbird/manifest.json index 0e9f03c8ef8..16dae205677 100644 --- a/homeassistant/components/doorbird/manifest.json +++ b/homeassistant/components/doorbird/manifest.json @@ -7,7 +7,7 @@ "documentation": "https://www.home-assistant.io/integrations/doorbird", "iot_class": "local_push", "loggers": ["doorbirdpy"], - "requirements": ["DoorBirdPy==3.0.2"], + "requirements": ["DoorBirdPy==3.0.3"], "zeroconf": [ { "type": "_axis-video._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index 1cdfc5956e2..2f7a00fda18 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -13,7 +13,7 @@ AIOSomecomfort==0.0.25 Adax-local==0.1.5 # homeassistant.components.doorbird -DoorBirdPy==3.0.2 +DoorBirdPy==3.0.3 # homeassistant.components.homekit HAP-python==4.9.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 24f9ccb5359..008fb616ec0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -13,7 +13,7 @@ AIOSomecomfort==0.0.25 Adax-local==0.1.5 # homeassistant.components.doorbird -DoorBirdPy==3.0.2 +DoorBirdPy==3.0.3 # homeassistant.components.homekit HAP-python==4.9.1 From 79b304a5d26258ef06d25b329b8123ddde2ddefe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 6 Oct 2024 17:07:27 -0500 Subject: [PATCH 23/89] Bump DoorBirdPy to 3.0.4 (#127760) changelog: https://gitlab.com/klikini/doorbirdpy/-/compare/3.0.3...eea287316c6fd84b63cc67fd743cc1128ea14568?from_project_id=7409088&straight=false fixes #126598 --- homeassistant/components/doorbird/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/doorbird/manifest.json b/homeassistant/components/doorbird/manifest.json index 16dae205677..153f552b698 100644 --- a/homeassistant/components/doorbird/manifest.json +++ b/homeassistant/components/doorbird/manifest.json @@ -7,7 +7,7 @@ "documentation": "https://www.home-assistant.io/integrations/doorbird", "iot_class": "local_push", "loggers": ["doorbirdpy"], - "requirements": ["DoorBirdPy==3.0.3"], + "requirements": ["DoorBirdPy==3.0.4"], "zeroconf": [ { "type": "_axis-video._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index 2f7a00fda18..835f48c73f2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -13,7 +13,7 @@ AIOSomecomfort==0.0.25 Adax-local==0.1.5 # homeassistant.components.doorbird -DoorBirdPy==3.0.3 +DoorBirdPy==3.0.4 # homeassistant.components.homekit HAP-python==4.9.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 008fb616ec0..a3c4aecac87 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -13,7 +13,7 @@ AIOSomecomfort==0.0.25 Adax-local==0.1.5 # homeassistant.components.doorbird -DoorBirdPy==3.0.3 +DoorBirdPy==3.0.4 # homeassistant.components.homekit HAP-python==4.9.1 From 60b9e65c788b58afba976b995b213a8f1016f762 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 7 Oct 2024 10:04:54 +0200 Subject: [PATCH 24/89] Bump pychromecast to 14.0.3 (#127778) --- 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 1d06ae23ca2..65f39a7171e 100644 --- a/homeassistant/components/cast/manifest.json +++ b/homeassistant/components/cast/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/cast", "iot_class": "local_polling", "loggers": ["casttube", "pychromecast"], - "requirements": ["PyChromecast==14.0.1"], + "requirements": ["PyChromecast==14.0.3"], "zeroconf": ["_googlecast._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 835f48c73f2..9d50a910a8f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -45,7 +45,7 @@ ProgettiHWSW==0.1.3 # PyBluez==0.22 # homeassistant.components.cast -PyChromecast==14.0.1 +PyChromecast==14.0.3 # homeassistant.components.flick_electric PyFlick==0.0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a3c4aecac87..1268d95bcc8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -42,7 +42,7 @@ PlexAPI==4.15.16 ProgettiHWSW==0.1.3 # homeassistant.components.cast -PyChromecast==14.0.1 +PyChromecast==14.0.3 # homeassistant.components.flick_electric PyFlick==0.0.2 From c087654386bb0d993dfcbde4d6d98a0f2e7ec809 Mon Sep 17 00:00:00 2001 From: Johan Gustafsson Date: Tue, 8 Oct 2024 11:31:59 +0200 Subject: [PATCH 25/89] Fix aurora alert sensor always Off (#127780) --- homeassistant/components/aurora/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/homeassistant/components/aurora/__init__.py b/homeassistant/components/aurora/__init__.py index 273f6c6fec2..b6c47cf36b2 100644 --- a/homeassistant/components/aurora/__init__.py +++ b/homeassistant/components/aurora/__init__.py @@ -4,6 +4,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform from homeassistant.core import HomeAssistant +from .const import CONF_THRESHOLD, DEFAULT_THRESHOLD from .coordinator import AuroraDataUpdateCoordinator PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR] @@ -21,9 +22,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: AuroraConfigEntry) -> bo await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + entry.async_on_unload(entry.add_update_listener(update_listener)) return True +async def update_listener(hass: HomeAssistant, entry: AuroraConfigEntry) -> None: + """Handle options update.""" + entry.runtime_data.threshold = int( + entry.options.get(CONF_THRESHOLD, DEFAULT_THRESHOLD) + ) + # refresh the state of the visibility alert binary sensor + await entry.runtime_data.async_request_refresh() + + async def async_unload_entry(hass: HomeAssistant, entry: AuroraConfigEntry) -> bool: """Unload a config entry.""" return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) From 8cd63b80b17e1aca976f536d15f3157213ae4ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 7 Oct 2024 11:19:34 +0200 Subject: [PATCH 26/89] Update aioairzone-cloud to v0.6.6 (#127789) --- homeassistant/components/airzone_cloud/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airzone_cloud/manifest.json b/homeassistant/components/airzone_cloud/manifest.json index e0b0695655d..b1d3400c9be 100644 --- a/homeassistant/components/airzone_cloud/manifest.json +++ b/homeassistant/components/airzone_cloud/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone_cloud", "iot_class": "cloud_push", "loggers": ["aioairzone_cloud"], - "requirements": ["aioairzone-cloud==0.6.5"] + "requirements": ["aioairzone-cloud==0.6.6"] } diff --git a/requirements_all.txt b/requirements_all.txt index 9d50a910a8f..e9080753d75 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -176,7 +176,7 @@ aio-georss-gdacs==0.10 aioairq==0.3.2 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.6.5 +aioairzone-cloud==0.6.6 # homeassistant.components.airzone aioairzone==0.9.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1268d95bcc8..addf9fd7ac8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -164,7 +164,7 @@ aio-georss-gdacs==0.10 aioairq==0.3.2 # homeassistant.components.airzone_cloud -aioairzone-cloud==0.6.5 +aioairzone-cloud==0.6.6 # homeassistant.components.airzone aioairzone==0.9.3 From c5772916a1938e313a4a7b95cb100a65eb56dd6b Mon Sep 17 00:00:00 2001 From: TimL Date: Mon, 7 Oct 2024 23:24:26 +1100 Subject: [PATCH 27/89] Bump pysmlight to v0.1.3 (#127804) Bump pysmlight v0.1.3 Co-authored-by: Tim Lunn --- homeassistant/components/smlight/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/smlight/manifest.json b/homeassistant/components/smlight/manifest.json index 10984e8efb1..c1eca45871b 100644 --- a/homeassistant/components/smlight/manifest.json +++ b/homeassistant/components/smlight/manifest.json @@ -6,7 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/smlight", "integration_type": "device", "iot_class": "local_push", - "requirements": ["pysmlight==0.1.2"], + "requirements": ["pysmlight==0.1.3"], "zeroconf": [ { "type": "_slzb-06._tcp.local." diff --git a/requirements_all.txt b/requirements_all.txt index e9080753d75..28b3348e56d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2244,7 +2244,7 @@ pysmarty2==0.10.1 pysml==0.0.12 # homeassistant.components.smlight -pysmlight==0.1.2 +pysmlight==0.1.3 # homeassistant.components.snmp pysnmp==6.2.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index addf9fd7ac8..c540709058c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1798,7 +1798,7 @@ pysmartthings==0.7.8 pysml==0.0.12 # homeassistant.components.smlight -pysmlight==0.1.2 +pysmlight==0.1.3 # homeassistant.components.snmp pysnmp==6.2.6 From 3be808ae1ecbfec81ff23f9abf0d100255c36421 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:15:23 +0200 Subject: [PATCH 28/89] Fix incorrect string in amberlectric (#127807) --- homeassistant/components/amberelectric/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/amberelectric/strings.json b/homeassistant/components/amberelectric/strings.json index ccdc2374142..684a5a2a0cc 100644 --- a/homeassistant/components/amberelectric/strings.json +++ b/homeassistant/components/amberelectric/strings.json @@ -10,7 +10,7 @@ }, "site": { "data": { - "site_nmi": "Site NMI", + "site_id": "Site NMI", "site_name": "Site Name" }, "description": "Select the NMI of the site you would like to add" From e35496133e360f17ecd2a82c641d02b7f673448f Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:43:40 +0200 Subject: [PATCH 29/89] Add missing and fix incorrect translation string in alarmdecoder (#127814) --- homeassistant/components/alarmdecoder/strings.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alarmdecoder/strings.json b/homeassistant/components/alarmdecoder/strings.json index dd698201b09..ccf1d965855 100644 --- a/homeassistant/components/alarmdecoder/strings.json +++ b/homeassistant/components/alarmdecoder/strings.json @@ -22,7 +22,8 @@ } }, "error": { - "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" + "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "unknown": "[%key:common::config_flow::error::unknown%]" }, "create_entry": { "default": "Successfully connected to AlarmDecoder." @@ -37,7 +38,7 @@ "title": "Configure AlarmDecoder", "description": "What would you like to edit?", "data": { - "edit_select": "Edit" + "edit_selection": "Edit" } }, "arm_settings": { From 91e4d8b663250a1539db18c0675443d094c9d778 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:45:41 +0200 Subject: [PATCH 30/89] Fix incorrect translation string in analytics_insights (#127815) --- homeassistant/components/analytics_insights/strings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/analytics_insights/strings.json b/homeassistant/components/analytics_insights/strings.json index 3b770f189a4..b036815259c 100644 --- a/homeassistant/components/analytics_insights/strings.json +++ b/homeassistant/components/analytics_insights/strings.json @@ -17,7 +17,7 @@ "unknown": "[%key:common::config_flow::error::unknown%]" }, "error": { - "no_integration_selected": "You must select at least one integration to track" + "no_integrations_selected": "You must select at least one integration to track" } }, "options": { @@ -37,7 +37,7 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" }, "error": { - "no_integration_selected": "[%key:component::analytics_insights::config::error::no_integration_selected%]" + "no_integrations_selected": "[%key:component::analytics_insights::config::error::no_integrations_selected%]" } }, "entity": { From dad2396d01cb249b5fee19ad2a80db1381d2dbb5 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:15:46 +0200 Subject: [PATCH 31/89] Add missing and fix incorrect translation string in aurora (#127818) --- homeassistant/components/aurora/strings.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/aurora/strings.json b/homeassistant/components/aurora/strings.json index 09ec86bdf4d..5ba3a1273fd 100644 --- a/homeassistant/components/aurora/strings.json +++ b/homeassistant/components/aurora/strings.json @@ -14,14 +14,15 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" }, "error": { - "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" + "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "unknown": "[%key:common::config_flow::error::unknown%]" } }, "options": { "step": { "init": { "data": { - "threshold": "Threshold (%)" + "forecast_threshold": "Threshold (%)" } } } From f0cb6381061ac3ffb41d1adac89af5767c4f58ae Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:44:23 +0200 Subject: [PATCH 32/89] Fix incorrect translation string in azure event hub (#127820) --- homeassistant/components/azure_event_hub/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/azure_event_hub/strings.json b/homeassistant/components/azure_event_hub/strings.json index 3f05e4b8e35..3319a29a154 100644 --- a/homeassistant/components/azure_event_hub/strings.json +++ b/homeassistant/components/azure_event_hub/strings.json @@ -38,7 +38,7 @@ }, "options": { "step": { - "options": { + "init": { "title": "Options for the Azure Event Hub.", "data": { "send_interval": "Interval between sending batches to the hub." From da1ac4f1e910525830a956d76f3fa6f965cf8c40 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 8 Oct 2024 09:39:21 +0200 Subject: [PATCH 33/89] Correct cleanup of sensor statistics repairs (#127826) --- homeassistant/components/sensor/recorder.py | 62 +++++++----- tests/components/sensor/test_recorder.py | 107 ++++++++++++++++++++ 2 files changed, 141 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/sensor/recorder.py b/homeassistant/components/sensor/recorder.py index 59f20a9ed25..675d24b9240 100644 --- a/homeassistant/components/sensor/recorder.py +++ b/homeassistant/components/sensor/recorder.py @@ -6,7 +6,6 @@ from collections import defaultdict from collections.abc import Callable, Iterable from contextlib import suppress import datetime -from functools import partial import itertools import logging import math @@ -39,6 +38,7 @@ from homeassistant.helpers.entity import entity_sources from homeassistant.helpers.typing import UNDEFINED, UndefinedType from homeassistant.loader import async_suggest_report_issue from homeassistant.util import dt as dt_util +from homeassistant.util.async_ import run_callback_threadsafe from homeassistant.util.enum import try_parse_enum from homeassistant.util.hass_dict import HassKey @@ -686,7 +686,6 @@ def list_statistic_ids( @callback def _update_issues( report_issue: Callable[[str, str, dict[str, Any]], None], - clear_issue: Callable[[str, str], None], sensor_states: list[State], metadatas: dict[str, tuple[int, StatisticMetaData]], ) -> None: @@ -707,8 +706,6 @@ def _update_issues( entity_id, {"statistic_id": entity_id}, ) - else: - clear_issue("state_class_removed", entity_id) metadata_unit = metadata[1]["unit_of_measurement"] converter = statistics.STATISTIC_UNIT_TO_UNIT_CONVERTER.get(metadata_unit) @@ -725,8 +722,6 @@ def _update_issues( "supported_unit": metadata_unit, }, ) - else: - clear_issue("units_changed", entity_id) elif numeric and state_unit not in converter.VALID_UNITS: # The state unit can't be converted to the unit in metadata valid_units = (unit or "" for unit in converter.VALID_UNITS) @@ -741,8 +736,6 @@ def _update_issues( "supported_unit": valid_units_str, }, ) - else: - clear_issue("units_changed", entity_id) def update_statistics_issues( @@ -756,36 +749,50 @@ def update_statistics_issues( instance, session, statistic_source=RECORDER_DOMAIN ) + @callback + def get_sensor_statistics_issues(hass: HomeAssistant) -> set[str]: + """Return a list of statistics issues.""" + issues = set() + issue_registry = ir.async_get(hass) + for issue in issue_registry.issues.values(): + if ( + issue.domain != DOMAIN + or not (issue_data := issue.data) + or issue_data.get("issue_type") + not in ("state_class_removed", "units_changed") + ): + continue + issues.add(issue.issue_id) + return issues + + issues = run_callback_threadsafe( + hass.loop, get_sensor_statistics_issues, hass + ).result() + def create_issue_registry_issue( issue_type: str, statistic_id: str, data: dict[str, Any] ) -> None: """Create an issue registry issue.""" - hass.loop.call_soon_threadsafe( - partial( - ir.async_create_issue, - hass, - DOMAIN, - f"{issue_type}_{statistic_id}", - data=data | {"issue_type": issue_type}, - is_fixable=False, - severity=ir.IssueSeverity.WARNING, - translation_key=issue_type, - translation_placeholders=data, - ) - ) - - def delete_issue_registry_issue(issue_type: str, statistic_id: str) -> None: - """Delete an issue registry issue.""" - hass.loop.call_soon_threadsafe( - ir.async_delete_issue, hass, DOMAIN, f"{issue_type}_{statistic_id}" + issue_id = f"{issue_type}_{statistic_id}" + issues.discard(issue_id) + ir.create_issue( + hass, + DOMAIN, + issue_id, + data=data | {"issue_type": issue_type}, + is_fixable=False, + severity=ir.IssueSeverity.WARNING, + translation_key=issue_type, + translation_placeholders=data, ) _update_issues( create_issue_registry_issue, - delete_issue_registry_issue, sensor_states, metadatas, ) + for issue_id in issues: + hass.loop.call_soon_threadsafe(ir.async_delete_issue, hass, DOMAIN, issue_id) def validate_statistics( @@ -811,7 +818,6 @@ def validate_statistics( _update_issues( create_statistic_validation_issue, - lambda issue_type, statistic_id: None, sensor_states, metadatas, ) diff --git a/tests/components/sensor/test_recorder.py b/tests/components/sensor/test_recorder.py index 04e0a1b7de8..37f080d2de2 100644 --- a/tests/components/sensor/test_recorder.py +++ b/tests/components/sensor/test_recorder.py @@ -4682,6 +4682,65 @@ async def test_validate_statistics_state_class_removed( await assert_validation_result(hass, client, {}, {}) +@pytest.mark.parametrize( + ("units", "attributes", "unit"), + [ + (US_CUSTOMARY_SYSTEM, POWER_SENSOR_ATTRIBUTES, "W"), + ], +) +async def test_validate_statistics_state_class_removed_issue_cleaned_up( + hass: HomeAssistant, + hass_ws_client: WebSocketGenerator, + units, + attributes, + unit, +) -> None: + """Test validate_statistics.""" + now = get_start_time(dt_util.utcnow()) + + hass.config.units = units + await async_setup_component(hass, "sensor", {}) + await async_recorder_block_till_done(hass) + client = await hass_ws_client() + + # No statistics, no state - empty response + await assert_validation_result(hass, client, {}, {}) + + # No statistics, valid state - empty response + hass.states.async_set( + "sensor.test", 10, attributes=attributes, timestamp=now.timestamp() + ) + await hass.async_block_till_done() + await assert_validation_result(hass, client, {}, {}) + + # Statistics has run, empty response + do_adhoc_statistics(hass, start=now) + await async_recorder_block_till_done(hass) + await assert_validation_result(hass, client, {}, {}) + + # State update with invalid state class, expect error + _attributes = dict(attributes) + _attributes.pop("state_class") + hass.states.async_set( + "sensor.test", 12, attributes=_attributes, timestamp=now.timestamp() + ) + await hass.async_block_till_done() + expected = { + "sensor.test": [ + { + "data": {"statistic_id": "sensor.test"}, + "type": "state_class_removed", + } + ], + } + await assert_validation_result(hass, client, expected, {"state_class_removed"}) + + # Remove the statistics - empty response + get_instance(hass).async_clear_statistics(["sensor.test"]) + await async_recorder_block_till_done(hass) + await assert_validation_result(hass, client, {}, {}) + + @pytest.mark.parametrize( ("units", "attributes", "unit"), [ @@ -5371,3 +5430,51 @@ async def test_exclude_attributes(hass: HomeAssistant) -> None: assert len(states) == 1 assert ATTR_OPTIONS not in states[0].attributes assert ATTR_FRIENDLY_NAME in states[0].attributes + + +async def test_clean_up_repairs( + hass: HomeAssistant, hass_ws_client: WebSocketGenerator +) -> None: + """Test cleaning up repairs.""" + await async_setup_component(hass, "sensor", {}) + issue_registry = ir.async_get(hass) + client = await hass_ws_client() + + # Create some issues + def create_issue(domain: str, issue_id: str, data: dict | None) -> None: + ir.async_create_issue( + hass, + domain, + issue_id, + data=data, + is_fixable=False, + severity=ir.IssueSeverity.WARNING, + translation_key="", + ) + + create_issue("test", "test_issue", None) + create_issue(DOMAIN, "test_issue_1", None) + create_issue(DOMAIN, "test_issue_2", {"issue_type": "another_issue"}) + create_issue(DOMAIN, "test_issue_3", {"issue_type": "state_class_removed"}) + create_issue(DOMAIN, "test_issue_4", {"issue_type": "units_changed"}) + + # Check the issues + assert set(issue_registry.issues) == { + ("test", "test_issue"), + ("sensor", "test_issue_1"), + ("sensor", "test_issue_2"), + ("sensor", "test_issue_3"), + ("sensor", "test_issue_4"), + } + + # Request update of issues + await client.send_json_auto_id({"type": "recorder/update_statistics_issues"}) + response = await client.receive_json() + assert response["success"] + + # Check the issues + assert set(issue_registry.issues) == { + ("test", "test_issue"), + ("sensor", "test_issue_1"), + ("sensor", "test_issue_2"), + } From 2bd7ce618acd385dea5779eb8165b7d57376928b Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:13:16 +0200 Subject: [PATCH 34/89] Add missing translation string in blebox (#127827) --- homeassistant/components/blebox/strings.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/blebox/strings.json b/homeassistant/components/blebox/strings.json index b179f0d097b..18c689e093d 100644 --- a/homeassistant/components/blebox/strings.json +++ b/homeassistant/components/blebox/strings.json @@ -15,7 +15,9 @@ "description": "Set up your BleBox to integrate with Home Assistant.", "data": { "host": "[%key:common::config_flow::data::ip%]", - "port": "[%key:common::config_flow::data::port%]" + "password": "[%key:common::config_flow::data::password%]", + "port": "[%key:common::config_flow::data::port%]", + "username": "[%key:common::config_flow::data::username%]" }, "title": "Set up your BleBox device" } From a481448d46348b6d3ea58f854a55514061cb12ef Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:42:34 +0200 Subject: [PATCH 35/89] Fix incorrect translation string in bryant_evolution (#127830) --- homeassistant/components/bryant_evolution/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/bryant_evolution/strings.json b/homeassistant/components/bryant_evolution/strings.json index d446fdc5345..9e2b5509cc4 100644 --- a/homeassistant/components/bryant_evolution/strings.json +++ b/homeassistant/components/bryant_evolution/strings.json @@ -1,7 +1,7 @@ { "config": { "step": { - "reconfigure": { + "reconfigure_confirm": { "data": { "filename": "[%key:component::bryant_evolution::config::step::user::data::filename%]" } From 41c794c73309434b10fd602d8f6e84f36e0de477 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:16:43 +0200 Subject: [PATCH 36/89] Add missing and fix incorrect translation string in duotecno (#127834) --- homeassistant/components/duotecno/strings.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/duotecno/strings.json b/homeassistant/components/duotecno/strings.json index a5585c3dd2c..2342eeb8288 100644 --- a/homeassistant/components/duotecno/strings.json +++ b/homeassistant/components/duotecno/strings.json @@ -5,18 +5,21 @@ "data": { "host": "[%key:common::config_flow::data::host%]", "username": "[%key:common::config_flow::data::username%]", - "password": "[%key:common::config_flow::data::password%]" + "password": "[%key:common::config_flow::data::password%]", + "port": "[%key:common::config_flow::data::port%]" }, "data_description": { "host": "The hostname or IP address of your Duotecno device." } } }, + "abort": { + "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" + }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", - "unknown": "[%key:common::config_flow::error::unknown%]", - "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" + "unknown": "[%key:common::config_flow::error::unknown%]" } }, "entity": { From e5644ae0118aae92feef36cba1f507be3c856c6f Mon Sep 17 00:00:00 2001 From: dontinelli <73341522+dontinelli@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:46:49 +0200 Subject: [PATCH 37/89] Reverse unintended change of unique_id for solarlog (#127845) --- homeassistant/components/solarlog/entity.py | 6 +- .../solarlog/snapshots/test_sensor.ambr | 105 +++++------------- 2 files changed, 30 insertions(+), 81 deletions(-) diff --git a/homeassistant/components/solarlog/entity.py b/homeassistant/components/solarlog/entity.py index 1d91fc8726b..b0f3ddf99f9 100644 --- a/homeassistant/components/solarlog/entity.py +++ b/homeassistant/components/solarlog/entity.py @@ -38,7 +38,7 @@ class SolarLogCoordinatorEntity(SolarLogBaseEntity): """Initialize the SolarLogCoordinator sensor.""" super().__init__(coordinator, description) - self._attr_unique_id = f"{coordinator.unique_id}-{description.key}" + self._attr_unique_id = f"{coordinator.unique_id}_{description.key}" self._attr_device_info = DeviceInfo( manufacturer="Solar-Log", model="Controller", @@ -59,8 +59,8 @@ class SolarLogInverterEntity(SolarLogBaseEntity): ) -> None: """Initialize the SolarLogInverter sensor.""" super().__init__(coordinator, description) - name = f"{coordinator.unique_id}-{slugify(coordinator.solarlog.device_name(device_id))}" - self._attr_unique_id = f"{name}-{description.key}" + name = f"{coordinator.unique_id}_{slugify(coordinator.solarlog.device_name(device_id))}" + self._attr_unique_id = f"{name}_{description.key}" self._attr_device_info = DeviceInfo( manufacturer="Solar-Log", model="Inverter", diff --git a/tests/components/solarlog/snapshots/test_sensor.ambr b/tests/components/solarlog/snapshots/test_sensor.ambr index 9f95e04a38f..38356a00de7 100644 --- a/tests/components/solarlog/snapshots/test_sensor.ambr +++ b/tests/components/solarlog/snapshots/test_sensor.ambr @@ -1,55 +1,4 @@ # serializer version: 1 -# name: test_all_entities[sensor.inverter_1_consumption_total-entry] - EntityRegistryEntrySnapshot({ - 'aliases': set({ - }), - 'area_id': None, - 'capabilities': dict({ - 'state_class': , - }), - 'config_entry_id': , - 'device_class': None, - 'device_id': , - 'disabled_by': None, - 'domain': 'sensor', - 'entity_category': None, - 'entity_id': 'sensor.inverter_1_consumption_total', - 'has_entity_name': True, - 'hidden_by': None, - 'icon': None, - 'id': , - 'labels': set({ - }), - 'name': None, - 'options': dict({ - }), - 'original_device_class': , - 'original_icon': None, - 'original_name': 'Consumption total', - 'platform': 'solarlog', - 'previous_unique_id': None, - 'supported_features': 0, - 'translation_key': 'consumption_total', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_1-consumption_total', - 'unit_of_measurement': , - }) -# --- -# name: test_all_entities[sensor.inverter_1_consumption_total-state] - StateSnapshot({ - 'attributes': ReadOnlyDict({ - 'device_class': 'energy', - 'friendly_name': 'Inverter 1 Consumption total', - 'state_class': , - 'unit_of_measurement': , - }), - 'context': , - 'entity_id': 'sensor.inverter_1_consumption_total', - 'last_changed': , - 'last_reported': , - 'last_updated': , - 'state': '354.687', - }) -# --- # name: test_all_entities[sensor.inverter_1_consumption_year-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -85,7 +34,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_year', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_1-consumption_year', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_inverter_1_consumption_year', 'unit_of_measurement': , }) # --- @@ -135,7 +84,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'current_power', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_1-current_power', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_inverter_1_current_power', 'unit_of_measurement': , }) # --- @@ -190,7 +139,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_year', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_2-consumption_year', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_inverter_2_consumption_year', 'unit_of_measurement': , }) # --- @@ -240,7 +189,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'current_power', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_2-current_power', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_inverter_2_current_power', 'unit_of_measurement': , }) # --- @@ -291,7 +240,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'alternator_loss', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-alternator_loss', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_alternator_loss', 'unit_of_measurement': , }) # --- @@ -345,7 +294,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'capacity', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-capacity', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_capacity', 'unit_of_measurement': '%', }) # --- @@ -396,7 +345,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_ac', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_ac', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_ac', 'unit_of_measurement': , }) # --- @@ -451,7 +400,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_day', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_day', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_day', 'unit_of_measurement': , }) # --- @@ -505,7 +454,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_month', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_month', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_month', 'unit_of_measurement': , }) # --- @@ -561,7 +510,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_total', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_total', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_total', 'unit_of_measurement': , }) # --- @@ -616,7 +565,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_year', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_year', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_year', 'unit_of_measurement': , }) # --- @@ -670,7 +619,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'consumption_yesterday', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-consumption_yesterday', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_consumption_yesterday', 'unit_of_measurement': , }) # --- @@ -723,7 +672,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'efficiency', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-efficiency', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_efficiency', 'unit_of_measurement': '%', }) # --- @@ -772,7 +721,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'total_power', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-total_power', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_total_power', 'unit_of_measurement': , }) # --- @@ -820,7 +769,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'last_update', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-last_updated', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_last_updated', 'unit_of_measurement': None, }) # --- @@ -869,7 +818,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'power_ac', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-power_ac', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_power_ac', 'unit_of_measurement': , }) # --- @@ -920,7 +869,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'power_available', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-power_available', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_power_available', 'unit_of_measurement': , }) # --- @@ -971,7 +920,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'power_dc', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-power_dc', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_power_dc', 'unit_of_measurement': , }) # --- @@ -1022,7 +971,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'self_consumption_year', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-self_consumption_year', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_self_consumption_year', 'unit_of_measurement': , }) # --- @@ -1076,7 +1025,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'usage', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-usage', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_usage', 'unit_of_measurement': '%', }) # --- @@ -1127,7 +1076,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'voltage_ac', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-voltage_ac', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_voltage_ac', 'unit_of_measurement': , }) # --- @@ -1178,7 +1127,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'voltage_dc', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-voltage_dc', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_voltage_dc', 'unit_of_measurement': , }) # --- @@ -1233,7 +1182,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'yield_day', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-yield_day', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_yield_day', 'unit_of_measurement': , }) # --- @@ -1287,7 +1236,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'yield_month', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-yield_month', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_yield_month', 'unit_of_measurement': , }) # --- @@ -1343,7 +1292,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'yield_total', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-yield_total', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_yield_total', 'unit_of_measurement': , }) # --- @@ -1395,7 +1344,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'yield_year', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-yield_year', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_yield_year', 'unit_of_measurement': , }) # --- @@ -1449,7 +1398,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'yield_yesterday', - 'unique_id': 'ce5f5431554d101905d31797e1232da8-yield_yesterday', + 'unique_id': 'ce5f5431554d101905d31797e1232da8_yield_yesterday', 'unit_of_measurement': , }) # --- From 456b80e6aecefb1197e20c371c80384ac39655b5 Mon Sep 17 00:00:00 2001 From: Jon Seager Date: Tue, 8 Oct 2024 07:07:45 +0100 Subject: [PATCH 38/89] Bump `pytouchlinesl` to 0.1.8 (#127859) --- homeassistant/components/touchline_sl/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/touchline_sl/manifest.json b/homeassistant/components/touchline_sl/manifest.json index 2329cb67e17..dd591cbf038 100644 --- a/homeassistant/components/touchline_sl/manifest.json +++ b/homeassistant/components/touchline_sl/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/touchline_sl", "integration_type": "hub", "iot_class": "cloud_polling", - "requirements": ["pytouchlinesl==0.1.7"] + "requirements": ["pytouchlinesl==0.1.8"] } diff --git a/requirements_all.txt b/requirements_all.txt index 28b3348e56d..2adaf5087a3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2413,7 +2413,7 @@ pytomorrowio==0.3.6 pytouchline==0.7 # homeassistant.components.touchline_sl -pytouchlinesl==0.1.7 +pytouchlinesl==0.1.8 # homeassistant.components.traccar # homeassistant.components.traccar_server diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c540709058c..c87e334d80f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1919,7 +1919,7 @@ pytile==2023.12.0 pytomorrowio==0.3.6 # homeassistant.components.touchline_sl -pytouchlinesl==0.1.7 +pytouchlinesl==0.1.8 # homeassistant.components.traccar # homeassistant.components.traccar_server From 5901c543da08a53d04cef8f09661cfb8d0358242 Mon Sep 17 00:00:00 2001 From: azerty9971 Date: Wed, 9 Oct 2024 12:24:09 +0200 Subject: [PATCH 39/89] Fix wrong DPTypes returned by Tuya's cloud (#127860) Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --- homeassistant/components/tuya/entity.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/tuya/entity.py b/homeassistant/components/tuya/entity.py index 99d81848a91..4d3710f7570 100644 --- a/homeassistant/components/tuya/entity.py +++ b/homeassistant/components/tuya/entity.py @@ -17,6 +17,17 @@ from homeassistant.helpers.entity import Entity from .const import DOMAIN, LOGGER, TUYA_HA_SIGNAL_UPDATE_ENTITY, DPCode, DPType from .util import remap_value +_DPTYPE_MAPPING: dict[str, DPType] = { + "Bitmap": DPType.RAW, + "bitmap": DPType.RAW, + "bool": DPType.BOOLEAN, + "enum": DPType.ENUM, + "json": DPType.JSON, + "raw": DPType.RAW, + "string": DPType.STRING, + "value": DPType.INTEGER, +} + @dataclass class IntegerTypeData: @@ -256,7 +267,13 @@ class TuyaEntity(Entity): order = ["function", "status_range"] for key in order: if dpcode in getattr(self.device, key): - return DPType(getattr(self.device, key)[dpcode].type) + current_type = getattr(self.device, key)[dpcode].type + try: + return DPType(current_type) + except ValueError: + # Sometimes, we get ill-formed DPTypes from the cloud, + # this fixes them and maps them to the correct DPType. + return _DPTYPE_MAPPING.get(current_type) return None From 14a3e5b771e4bf5842141cb62074846c013235e8 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:40:58 +0200 Subject: [PATCH 40/89] Add missing translation string in AVM Fritz!Smarthome (#127864) --- homeassistant/components/fritzbox/strings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/fritzbox/strings.json b/homeassistant/components/fritzbox/strings.json index d4f59fd1c08..2b7dbff0a20 100644 --- a/homeassistant/components/fritzbox/strings.json +++ b/homeassistant/components/fritzbox/strings.json @@ -47,6 +47,7 @@ "reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]" }, "error": { + "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" } }, From a1e42cac7a16363ace58a8ef809544a12a0a0524 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Tue, 8 Oct 2024 18:35:06 +0200 Subject: [PATCH 41/89] Fix merge_response template not mutate original object (#127865) * Fix merge_response template not mutate original object * Add comment --- homeassistant/helpers/template.py | 4 +++- tests/helpers/test_template.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 9f8eb628e63..6d56fe708d0 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -9,6 +9,7 @@ import collections.abc from collections.abc import Callable, Generator, Iterable from contextlib import AbstractContextManager from contextvars import ContextVar +from copy import deepcopy from datetime import date, datetime, time, timedelta from functools import cache, cached_property, lru_cache, partial, wraps import json @@ -2166,7 +2167,8 @@ def merge_response(value: ServiceResponse) -> list[Any]: is_single_list = False response_items: list = [] - for entity_id, entity_response in value.items(): # pylint: disable=too-many-nested-blocks + input_service_response = deepcopy(value) + for entity_id, entity_response in input_service_response.items(): # pylint: disable=too-many-nested-blocks if not isinstance(entity_response, dict): raise TypeError("Response is not a dictionary") for value_key, type_response in entity_response.items(): diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 339b372f137..9a594408465 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -6564,3 +6564,21 @@ def test_warn_no_hass(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) -> template.Template("blah", hass) assert message not in caplog.text caplog.clear() + + +async def test_merge_response_not_mutate_original_object( + hass: HomeAssistant, snapshot: SnapshotAssertion +) -> None: + """Test the merge_response does not mutate original service response value.""" + + value = '{"calendar.family": {"events": [{"summary": "An event"}]}' + _template = ( + "{% set calendar_response = " + value + "} %}" + "{{ merge_response(calendar_response) }}" + # We should be able to merge the same response again + # as the merge is working on a copy of the original object (response) + "{{ merge_response(calendar_response) }}" + ) + + tpl = template.Template(_template, hass) + assert tpl.async_render() From c31e0336dcd0e1bdaadad5af2c5a96d1ab6e4dd3 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Wed, 9 Oct 2024 10:44:54 +0200 Subject: [PATCH 42/89] Don't error with missing information in systemmonitor diagnostics (#127868) --- .../components/systemmonitor/coordinator.py | 20 +++++-- .../snapshots/test_diagnostics.ambr | 55 +++++++++++++++++++ .../systemmonitor/test_diagnostics.py | 24 ++++++++ 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/systemmonitor/coordinator.py b/homeassistant/components/systemmonitor/coordinator.py index d12eddbb14a..32a171a11ca 100644 --- a/homeassistant/components/systemmonitor/coordinator.py +++ b/homeassistant/components/systemmonitor/coordinator.py @@ -37,17 +37,29 @@ class SensorData: def as_dict(self) -> dict[str, Any]: """Return as dict.""" + disk_usage = None + if self.disk_usage: + disk_usage = {k: str(v) for k, v in self.disk_usage.items()} + io_counters = None + if self.io_counters: + io_counters = {k: str(v) for k, v in self.io_counters.items()} + addresses = None + if self.addresses: + addresses = {k: str(v) for k, v in self.addresses.items()} + temperatures = None + if self.temperatures: + temperatures = {k: str(v) for k, v in self.temperatures.items()} return { - "disk_usage": {k: str(v) for k, v in self.disk_usage.items()}, + "disk_usage": disk_usage, "swap": str(self.swap), "memory": str(self.memory), - "io_counters": {k: str(v) for k, v in self.io_counters.items()}, - "addresses": {k: str(v) for k, v in self.addresses.items()}, + "io_counters": io_counters, + "addresses": addresses, "load": str(self.load), "cpu_percent": str(self.cpu_percent), "boot_time": str(self.boot_time), "processes": str(self.processes), - "temperatures": {k: str(v) for k, v in self.temperatures.items()}, + "temperatures": temperatures, } diff --git a/tests/components/systemmonitor/snapshots/test_diagnostics.ambr b/tests/components/systemmonitor/snapshots/test_diagnostics.ambr index 303074e3c2c..75d942fc601 100644 --- a/tests/components/systemmonitor/snapshots/test_diagnostics.ambr +++ b/tests/components/systemmonitor/snapshots/test_diagnostics.ambr @@ -62,3 +62,58 @@ }), }) # --- +# name: test_diagnostics_missing_items[test_diagnostics_missing_items] + dict({ + 'coordinators': dict({ + 'data': dict({ + 'addresses': None, + 'boot_time': '2024-02-24 15:00:00+00:00', + 'cpu_percent': '10.0', + 'disk_usage': dict({ + '/': 'sdiskusage(total=536870912000, used=322122547200, free=214748364800, percent=60.0)', + '/home/notexist/': 'sdiskusage(total=536870912000, used=322122547200, free=214748364800, percent=60.0)', + '/media/share': 'sdiskusage(total=536870912000, used=322122547200, free=214748364800, percent=60.0)', + }), + 'io_counters': None, + 'load': '(1, 2, 3)', + 'memory': 'VirtualMemory(total=104857600, available=41943040, percent=40.0, used=62914560, free=31457280)', + 'processes': "[tests.components.systemmonitor.conftest.MockProcess(pid=1, name='python3', status='sleeping', started='2024-02-23 15:00:00'), tests.components.systemmonitor.conftest.MockProcess(pid=1, name='pip', status='sleeping', started='2024-02-23 15:00:00')]", + 'swap': 'sswap(total=104857600, used=62914560, free=41943040, percent=60.0, sin=1, sout=1)', + 'temperatures': dict({ + 'cpu0-thermal': "[shwtemp(label='cpu0-thermal', current=50.0, high=60.0, critical=70.0)]", + }), + }), + 'last_update_success': True, + }), + 'entry': dict({ + 'data': dict({ + }), + 'disabled_by': None, + 'discovery_keys': dict({ + }), + 'domain': 'systemmonitor', + 'minor_version': 3, + 'options': dict({ + 'binary_sensor': dict({ + 'process': list([ + 'python3', + 'pip', + ]), + }), + 'resources': list([ + 'disk_use_percent_/', + 'disk_use_percent_/home/notexist/', + 'memory_free_', + 'network_out_eth0', + 'process_python3', + ]), + }), + 'pref_disable_new_entities': False, + 'pref_disable_polling': False, + 'source': 'user', + 'title': 'System Monitor', + 'unique_id': None, + 'version': 1, + }), + }) +# --- diff --git a/tests/components/systemmonitor/test_diagnostics.py b/tests/components/systemmonitor/test_diagnostics.py index b0f4fca3d0c..26e421e6574 100644 --- a/tests/components/systemmonitor/test_diagnostics.py +++ b/tests/components/systemmonitor/test_diagnostics.py @@ -2,6 +2,7 @@ from unittest.mock import Mock +from freezegun.api import FrozenDateTimeFactory from syrupy import SnapshotAssertion from syrupy.filters import props @@ -24,3 +25,26 @@ async def test_diagnostics( assert await get_diagnostics_for_config_entry( hass, hass_client, mock_added_config_entry ) == snapshot(exclude=props("last_update", "entry_id", "created_at", "modified_at")) + + +async def test_diagnostics_missing_items( + hass: HomeAssistant, + hass_client: ClientSessionGenerator, + mock_psutil: Mock, + mock_os: Mock, + mock_config_entry: MockConfigEntry, + snapshot: SnapshotAssertion, + freezer: FrozenDateTimeFactory, +) -> None: + """Test diagnostics.""" + mock_psutil.net_if_addrs.return_value = None + mock_psutil.net_io_counters.return_value = None + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + + assert await get_diagnostics_for_config_entry( + hass, hass_client, mock_config_entry + ) == snapshot( + exclude=props("last_update", "entry_id", "created_at", "modified_at"), + name="test_diagnostics_missing_items", + ) From bfcabeaf26e896cfce132a29b583d3b86bd09875 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Tue, 8 Oct 2024 08:09:03 +0200 Subject: [PATCH 43/89] Bump holidays library to 0.58 (#127876) --- homeassistant/components/holiday/manifest.json | 2 +- homeassistant/components/workday/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/holiday/manifest.json b/homeassistant/components/holiday/manifest.json index 30cfd34e0fb..559f18b331a 100644 --- a/homeassistant/components/holiday/manifest.json +++ b/homeassistant/components/holiday/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/holiday", "iot_class": "local_polling", - "requirements": ["holidays==0.57", "babel==2.15.0"] + "requirements": ["holidays==0.58", "babel==2.15.0"] } diff --git a/homeassistant/components/workday/manifest.json b/homeassistant/components/workday/manifest.json index 1201354bab2..cf3afb5fc37 100644 --- a/homeassistant/components/workday/manifest.json +++ b/homeassistant/components/workday/manifest.json @@ -7,5 +7,5 @@ "iot_class": "local_polling", "loggers": ["holidays"], "quality_scale": "internal", - "requirements": ["holidays==0.57"] + "requirements": ["holidays==0.58"] } diff --git a/requirements_all.txt b/requirements_all.txt index 2adaf5087a3..7cee89a01d5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1114,7 +1114,7 @@ hole==0.8.0 # homeassistant.components.holiday # homeassistant.components.workday -holidays==0.57 +holidays==0.58 # homeassistant.components.frontend home-assistant-frontend==20241002.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c87e334d80f..18f14230535 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -940,7 +940,7 @@ hole==0.8.0 # homeassistant.components.holiday # homeassistant.components.workday -holidays==0.57 +holidays==0.58 # homeassistant.components.frontend home-assistant-frontend==20241002.2 From 3021d38b6fc54a1e5ea3e7c8e75ad8a96b5f8a4d Mon Sep 17 00:00:00 2001 From: dcmeglio <21957250+dcmeglio@users.noreply.github.com> Date: Tue, 8 Oct 2024 02:11:25 -0400 Subject: [PATCH 44/89] Bump pyeconet to 0.1.23 (#127896) --- homeassistant/components/econet/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/econet/manifest.json b/homeassistant/components/econet/manifest.json index c96867b489b..6586af92d1f 100644 --- a/homeassistant/components/econet/manifest.json +++ b/homeassistant/components/econet/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/econet", "iot_class": "cloud_push", "loggers": ["paho_mqtt", "pyeconet"], - "requirements": ["pyeconet==0.1.22"] + "requirements": ["pyeconet==0.1.23"] } diff --git a/requirements_all.txt b/requirements_all.txt index 7cee89a01d5..15ad6be7c5d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1855,7 +1855,7 @@ pyebox==1.1.4 pyecoforest==0.4.0 # homeassistant.components.econet -pyeconet==0.1.22 +pyeconet==0.1.23 # homeassistant.components.ista_ecotrend pyecotrend-ista==3.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 18f14230535..4bab84af2cf 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1493,7 +1493,7 @@ pydroid-ipcam==2.0.0 pyecoforest==0.4.0 # homeassistant.components.econet -pyeconet==0.1.22 +pyeconet==0.1.23 # homeassistant.components.ista_ecotrend pyecotrend-ista==3.3.1 From dd076f7a13c0bc6910c4b4feb9bffa00b8d745f4 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:00:45 +0200 Subject: [PATCH 45/89] Add missing translation string in otbr (#127909) --- homeassistant/components/otbr/strings.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/otbr/strings.json b/homeassistant/components/otbr/strings.json index bc7812c1db7..e1afa5b8909 100644 --- a/homeassistant/components/otbr/strings.json +++ b/homeassistant/components/otbr/strings.json @@ -13,7 +13,9 @@ "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]" }, "abort": { - "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]" + "already_configured": "The Thread border router is already configured", + "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", + "unknown": "[%key:common::config_flow::error::unknown%]" } }, "issues": { From ee599160b3f87e2765476e0718193d491615ea68 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:52:54 +0200 Subject: [PATCH 46/89] Add missing translation string in yamaha_musiccast (#127912) --- homeassistant/components/yamaha_musiccast/strings.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/yamaha_musiccast/strings.json b/homeassistant/components/yamaha_musiccast/strings.json index d0ee6c030a6..eaa5ac50c80 100644 --- a/homeassistant/components/yamaha_musiccast/strings.json +++ b/homeassistant/components/yamaha_musiccast/strings.json @@ -20,7 +20,9 @@ "yxc_control_url_missing": "The control URL is not given in the ssdp description." }, "error": { - "no_musiccast_device": "This device seems to be no MusicCast Device." + "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", + "no_musiccast_device": "This device seems to be no MusicCast Device.", + "unknown": "[%key:common::config_flow::error::unknown%]" } }, "entity": { From ce359a7689acd01adf6f3b40065c1e886a2749aa Mon Sep 17 00:00:00 2001 From: Manu <4445816+tr4nt0r@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:08:16 +0200 Subject: [PATCH 47/89] Add support of due date calculation for grey dailies in Habitica integration (#127923) Fix grey dailies due date calculation --- homeassistant/components/habitica/util.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/habitica/util.py b/homeassistant/components/habitica/util.py index 0ac3ea2a4e2..26549e29cb0 100644 --- a/homeassistant/components/habitica/util.py +++ b/homeassistant/components/habitica/util.py @@ -14,6 +14,9 @@ from homeassistant.util import dt as dt_util def next_due_date(task: dict[str, Any], last_cron: str) -> datetime.date | None: """Calculate due date for dailies and yesterdailies.""" + if task["everyX"] == 0 or not task.get("nextDue"): # grey dailies never become due + return None + today = to_date(last_cron) startdate = to_date(task["startDate"]) if TYPE_CHECKING: From 094996ad0c3e45a1dd94d573f482131a285d5dd6 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Tue, 8 Oct 2024 13:58:03 +0200 Subject: [PATCH 48/89] Bump `imgw_pib` library to version 1.0.6 (#127925) Bump `imgw_pib` --- homeassistant/components/imgw_pib/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/imgw_pib/manifest.json b/homeassistant/components/imgw_pib/manifest.json index 08946a802f1..c01be10fc68 100644 --- a/homeassistant/components/imgw_pib/manifest.json +++ b/homeassistant/components/imgw_pib/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/imgw_pib", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["imgw_pib==1.0.5"] + "requirements": ["imgw_pib==1.0.6"] } diff --git a/requirements_all.txt b/requirements_all.txt index 15ad6be7c5d..0a643ac13c7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1176,7 +1176,7 @@ iglo==1.2.7 ihcsdk==2.8.5 # homeassistant.components.imgw_pib -imgw_pib==1.0.5 +imgw_pib==1.0.6 # homeassistant.components.incomfort incomfort-client==0.6.3-1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4bab84af2cf..f5a44367db8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -987,7 +987,7 @@ idasen-ha==2.6.2 ifaddr==0.2.0 # homeassistant.components.imgw_pib -imgw_pib==1.0.5 +imgw_pib==1.0.6 # homeassistant.components.incomfort incomfort-client==0.6.3-1 From a1c9d53474d5bc9760b29bc5b700eb593c87a24a Mon Sep 17 00:00:00 2001 From: "Steven B." <51370195+sdb9696@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:47:12 +0100 Subject: [PATCH 49/89] Bump python-kasa to 0.7.5 (#127934) --- homeassistant/components/tplink/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/tplink/manifest.json b/homeassistant/components/tplink/manifest.json index 81506c41a6d..ab1eac7d0c0 100644 --- a/homeassistant/components/tplink/manifest.json +++ b/homeassistant/components/tplink/manifest.json @@ -301,5 +301,5 @@ "iot_class": "local_polling", "loggers": ["kasa"], "quality_scale": "platinum", - "requirements": ["python-kasa[speedups]==0.7.4"] + "requirements": ["python-kasa[speedups]==0.7.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index 0a643ac13c7..26ffa805bc7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2340,7 +2340,7 @@ python-join-api==0.0.9 python-juicenet==1.1.0 # homeassistant.components.tplink -python-kasa[speedups]==0.7.4 +python-kasa[speedups]==0.7.5 # homeassistant.components.linkplay python-linkplay==0.0.15 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f5a44367db8..186d71e966a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1861,7 +1861,7 @@ python-izone==1.2.9 python-juicenet==1.1.0 # homeassistant.components.tplink -python-kasa[speedups]==0.7.4 +python-kasa[speedups]==0.7.5 # homeassistant.components.linkplay python-linkplay==0.0.15 From 0aabde081b54e84bd818b428727b7ec6e951383b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=B6rsken?= Date: Wed, 9 Oct 2024 17:18:58 +0200 Subject: [PATCH 50/89] Fix discovery of WMS WebControl pro by using IP address (#127939) --- homeassistant/components/wmspro/config_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/wmspro/config_flow.py b/homeassistant/components/wmspro/config_flow.py index ba3b5ef367d..19b9ab28e6a 100644 --- a/homeassistant/components/wmspro/config_flow.py +++ b/homeassistant/components/wmspro/config_flow.py @@ -75,7 +75,7 @@ class WebControlProConfigFlow(ConfigFlow, domain=DOMAIN): if self.source == dhcp.DOMAIN: discovery_info: DhcpServiceInfo = self.init_data - data_values = {CONF_HOST: discovery_info.hostname or discovery_info.ip} + data_values = {CONF_HOST: discovery_info.ip} else: data_values = {CONF_HOST: SUGGESTED_HOST} From e37025c1c74d0f2bd5589acf06cfc41498269414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=B6rsken?= Date: Wed, 9 Oct 2024 10:31:44 +0200 Subject: [PATCH 51/89] Update pywmspro to 0.2.1 to fix handling of unknown products (#127942) --- homeassistant/components/wmspro/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/wmspro/snapshots/test_diagnostics.ambr | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/wmspro/manifest.json b/homeassistant/components/wmspro/manifest.json index 3e0c4e21e6c..f174bcc89c7 100644 --- a/homeassistant/components/wmspro/manifest.json +++ b/homeassistant/components/wmspro/manifest.json @@ -15,5 +15,5 @@ "documentation": "https://www.home-assistant.io/integrations/wmspro", "integration_type": "hub", "iot_class": "local_polling", - "requirements": ["pywmspro==0.2.0"] + "requirements": ["pywmspro==0.2.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 26ffa805bc7..04372465c24 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2477,7 +2477,7 @@ pywilight==0.0.74 pywizlight==0.5.14 # homeassistant.components.wmspro -pywmspro==0.2.0 +pywmspro==0.2.1 # homeassistant.components.ws66i pyws66i==1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 186d71e966a..e5f16da0640 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1977,7 +1977,7 @@ pywilight==0.0.74 pywizlight==0.5.14 # homeassistant.components.wmspro -pywmspro==0.2.0 +pywmspro==0.2.1 # homeassistant.components.ws66i pyws66i==1.1 diff --git a/tests/components/wmspro/snapshots/test_diagnostics.ambr b/tests/components/wmspro/snapshots/test_diagnostics.ambr index 6a87c0416ab..00cb62e18c4 100644 --- a/tests/components/wmspro/snapshots/test_diagnostics.ambr +++ b/tests/components/wmspro/snapshots/test_diagnostics.ambr @@ -149,6 +149,8 @@ }), 'status': dict({ }), + 'unknownProducts': dict({ + }), }), '97358': dict({ 'actions': dict({ @@ -203,6 +205,8 @@ }), 'status': dict({ }), + 'unknownProducts': dict({ + }), }), }), 'host': 'webcontrol', From 8c80f47a357716b153cfc129ebc905267261feff Mon Sep 17 00:00:00 2001 From: Antoine Reversat Date: Fri, 11 Oct 2024 07:14:47 -0400 Subject: [PATCH 52/89] Fix europe authentication in Fujitsu FGLair (#127947) --- homeassistant/components/fujitsu_fglair/const.py | 2 +- homeassistant/components/fujitsu_fglair/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/fujitsu_fglair/const.py b/homeassistant/components/fujitsu_fglair/const.py index 8aa911a8b30..73c811a1ed5 100644 --- a/homeassistant/components/fujitsu_fglair/const.py +++ b/homeassistant/components/fujitsu_fglair/const.py @@ -9,5 +9,5 @@ DOMAIN = "fujitsu_fglair" CONF_REGION = "region" CONF_EUROPE = "is_europe" -REGION_EU = "EU" +REGION_EU = "eu" REGION_DEFAULT = "default" diff --git a/homeassistant/components/fujitsu_fglair/manifest.json b/homeassistant/components/fujitsu_fglair/manifest.json index 76cf3966fbe..1c7b9b0b469 100644 --- a/homeassistant/components/fujitsu_fglair/manifest.json +++ b/homeassistant/components/fujitsu_fglair/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/fujitsu_fglair", "iot_class": "cloud_polling", - "requirements": ["ayla-iot-unofficial==1.4.1"] + "requirements": ["ayla-iot-unofficial==1.4.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 04372465c24..af169cbd8be 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -532,7 +532,7 @@ autarco==3.0.0 axis==62 # homeassistant.components.fujitsu_fglair -ayla-iot-unofficial==1.4.1 +ayla-iot-unofficial==1.4.2 # homeassistant.components.azure_event_hub azure-eventhub==5.11.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e5f16da0640..9cb652302a4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -481,7 +481,7 @@ autarco==3.0.0 axis==62 # homeassistant.components.fujitsu_fglair -ayla-iot-unofficial==1.4.1 +ayla-iot-unofficial==1.4.2 # homeassistant.components.azure_event_hub azure-eventhub==5.11.1 From 66c2fe091b2b0ad6d9b90619e9b3ccb3eb714b8c Mon Sep 17 00:00:00 2001 From: Lenn <78048721+LennP@users.noreply.github.com> Date: Wed, 9 Oct 2024 10:33:29 +0200 Subject: [PATCH 53/89] Bump motionblindsble to 0.1.2 (#127954) --- homeassistant/components/motionblinds_ble/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/motionblinds_ble/manifest.json b/homeassistant/components/motionblinds_ble/manifest.json index d9968cfde4c..ce7e7a6bb8b 100644 --- a/homeassistant/components/motionblinds_ble/manifest.json +++ b/homeassistant/components/motionblinds_ble/manifest.json @@ -14,5 +14,5 @@ "integration_type": "device", "iot_class": "assumed_state", "loggers": ["motionblindsble"], - "requirements": ["motionblindsble==0.1.1"] + "requirements": ["motionblindsble==0.1.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index af169cbd8be..fb185a87705 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1387,7 +1387,7 @@ mopeka-iot-ble==0.8.0 motionblinds==0.6.25 # homeassistant.components.motionblinds_ble -motionblindsble==0.1.1 +motionblindsble==0.1.2 # homeassistant.components.motioneye motioneye-client==0.3.14 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9cb652302a4..c48ab4c650e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1156,7 +1156,7 @@ mopeka-iot-ble==0.8.0 motionblinds==0.6.25 # homeassistant.components.motionblinds_ble -motionblindsble==0.1.1 +motionblindsble==0.1.2 # homeassistant.components.motioneye motioneye-client==0.3.14 From ed445d20b98b93dbe80989a08682d1967a40d65d Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Wed, 9 Oct 2024 01:35:41 -0400 Subject: [PATCH 54/89] Fix zwave_js config validation for values (#127972) --- .../components/zwave_js/config_validation.py | 2 + .../zwave_js/test_config_validation.py | 42 ++++++++++--------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/zwave_js/config_validation.py b/homeassistant/components/zwave_js/config_validation.py index 6c060f90ce5..30bc2f16789 100644 --- a/homeassistant/components/zwave_js/config_validation.py +++ b/homeassistant/components/zwave_js/config_validation.py @@ -34,6 +34,8 @@ def boolean(value: Any) -> bool: VALUE_SCHEMA = vol.Any( boolean, + float, + int, vol.Coerce(int), vol.Coerce(float), BITMASK_SCHEMA, diff --git a/tests/components/zwave_js/test_config_validation.py b/tests/components/zwave_js/test_config_validation.py index 8428972bde1..cebbde3c9b1 100644 --- a/tests/components/zwave_js/test_config_validation.py +++ b/tests/components/zwave_js/test_config_validation.py @@ -1,27 +1,31 @@ """Test the Z-Wave JS config validation helpers.""" +from typing import Any + import pytest import voluptuous as vol -from homeassistant.components.zwave_js.config_validation import boolean +from homeassistant.components.zwave_js.config_validation import VALUE_SCHEMA, boolean -def test_boolean_validation() -> None: - """Test boolean config validator.""" - # test bool - assert boolean(True) - assert not boolean(False) - # test strings - assert boolean("TRUE") - assert not boolean("FALSE") - assert boolean("ON") - assert not boolean("NO") - # ensure 1's and 0's don't get converted to bool +@pytest.mark.parametrize( + ("test_cases", "expected_value"), + [ + ([True, "true", "yes", "on", "ON", "enable"], True), + ([False, "false", "no", "off", "NO", "disable"], False), + ([1.1, "1.1"], 1.1), + ([1.0, "1.0"], 1.0), + ([1, "1"], 1), + ], +) +def test_validation(test_cases: list[Any], expected_value: Any) -> None: + """Test config validation.""" + for case in test_cases: + assert VALUE_SCHEMA(case) == expected_value + + +@pytest.mark.parametrize("value", ["invalid", "1", "0", 1, 0]) +def test_invalid_boolean_validation(value: str | int) -> None: + """Test invalid cases for boolean config validator.""" with pytest.raises(vol.Invalid): - boolean("1") - with pytest.raises(vol.Invalid): - boolean("0") - with pytest.raises(vol.Invalid): - boolean(1) - with pytest.raises(vol.Invalid): - boolean(0) + boolean(value) From 33617694cc9b781e2ec01741bec316f1de4793fd Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 9 Oct 2024 09:56:53 +0200 Subject: [PATCH 55/89] Fix firmware version parsing in venstar (#127974) --- homeassistant/components/venstar/entity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/venstar/entity.py b/homeassistant/components/venstar/entity.py index 630da05324e..b8a4b971a7f 100644 --- a/homeassistant/components/venstar/entity.py +++ b/homeassistant/components/venstar/entity.py @@ -34,11 +34,11 @@ class VenstarEntity(CoordinatorEntity[VenstarDataUpdateCoordinator]): @property def device_info(self) -> DeviceInfo: """Return the device information for this entity.""" - fw_ver_major, fw_ver_minor = self._client.get_firmware_ver() + firmware_version = self._client.get_firmware_ver() return DeviceInfo( identifiers={(DOMAIN, self._config.entry_id)}, name=self._client.name, manufacturer="Venstar", model=f"{self._client.model}-{self._client.get_type()}", - sw_version=f"{fw_ver_major}.{fw_ver_minor}", + sw_version=f"{firmware_version[0]}.{firmware_version[1]}", ) From 44743df7d6c7faf3808219eb93ae2d3571e12bb9 Mon Sep 17 00:00:00 2001 From: Maikel Punie Date: Wed, 9 Oct 2024 12:20:27 +0200 Subject: [PATCH 56/89] Bump pyduotecno to 2024.10.0 (#127979) --- homeassistant/components/duotecno/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/duotecno/manifest.json b/homeassistant/components/duotecno/manifest.json index 8f8740ddfdf..37ed4457184 100644 --- a/homeassistant/components/duotecno/manifest.json +++ b/homeassistant/components/duotecno/manifest.json @@ -7,5 +7,5 @@ "iot_class": "local_push", "loggers": ["pyduotecno", "pyduotecno-node", "pyduotecno-unit"], "quality_scale": "silver", - "requirements": ["pyDuotecno==2024.9.0"] + "requirements": ["pyDuotecno==2024.10.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index fb185a87705..791d1e1faa2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1710,7 +1710,7 @@ pyCEC==0.5.2 pyControl4==1.2.0 # homeassistant.components.duotecno -pyDuotecno==2024.9.0 +pyDuotecno==2024.10.0 # homeassistant.components.electrasmart pyElectra==1.2.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c48ab4c650e..ca0008d8866 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1396,7 +1396,7 @@ pyCEC==0.5.2 pyControl4==1.2.0 # homeassistant.components.duotecno -pyDuotecno==2024.9.0 +pyDuotecno==2024.10.0 # homeassistant.components.electrasmart pyElectra==1.2.4 From 635731421f6cbf455295e4dd9e6da4e073d4279f Mon Sep 17 00:00:00 2001 From: "Teemu R." Date: Fri, 11 Oct 2024 13:15:30 +0200 Subject: [PATCH 57/89] Increase tplink climate precision (#127996) --- homeassistant/components/tplink/climate.py | 4 ++-- tests/components/tplink/snapshots/test_climate.ambr | 4 ++-- tests/components/tplink/test_climate.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/tplink/climate.py b/homeassistant/components/tplink/climate.py index 3bd6aba5c26..f86992ea0cf 100644 --- a/homeassistant/components/tplink/climate.py +++ b/homeassistant/components/tplink/climate.py @@ -15,7 +15,7 @@ from homeassistant.components.climate import ( HVACAction, HVACMode, ) -from homeassistant.const import PRECISION_WHOLE +from homeassistant.const import PRECISION_TENTHS from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ServiceValidationError from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -64,7 +64,7 @@ class TPLinkClimateEntity(CoordinatedTPLinkEntity, ClimateEntity): | ClimateEntityFeature.TURN_ON ) _attr_hvac_modes = [HVACMode.HEAT, HVACMode.OFF] - _attr_precision = PRECISION_WHOLE + _attr_precision = PRECISION_TENTHS # This disables the warning for async_turn_{on,off}, can be removed later. _enable_turn_on_off_backwards_compatibility = False diff --git a/tests/components/tplink/snapshots/test_climate.ambr b/tests/components/tplink/snapshots/test_climate.ambr index ad863fc79ae..8236f332046 100644 --- a/tests/components/tplink/snapshots/test_climate.ambr +++ b/tests/components/tplink/snapshots/test_climate.ambr @@ -42,7 +42,7 @@ # name: test_states[climate.thermostat-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'current_temperature': 20, + 'current_temperature': 20.2, 'friendly_name': 'thermostat', 'hvac_action': , 'hvac_modes': list([ @@ -52,7 +52,7 @@ 'max_temp': 65536, 'min_temp': None, 'supported_features': , - 'temperature': 22, + 'temperature': 22.2, }), 'context': , 'entity_id': 'climate.thermostat', diff --git a/tests/components/tplink/test_climate.py b/tests/components/tplink/test_climate.py index 2f24fa829f9..3a54048e1d6 100644 --- a/tests/components/tplink/test_climate.py +++ b/tests/components/tplink/test_climate.py @@ -45,11 +45,11 @@ async def mocked_hub(hass: HomeAssistant) -> Device: features = [ _mocked_feature( - "temperature", value=20, category=Feature.Category.Primary, unit="celsius" + "temperature", value=20.2, category=Feature.Category.Primary, unit="celsius" ), _mocked_feature( "target_temperature", - value=22, + value=22.2, type_=Feature.Type.Number, category=Feature.Category.Primary, unit="celsius", @@ -94,8 +94,8 @@ async def test_climate( state = hass.states.get(ENTITY_ID) assert state.attributes[ATTR_HVAC_ACTION] is HVACAction.HEATING - assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 20 - assert state.attributes[ATTR_TEMPERATURE] == 22 + assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 20.2 + assert state.attributes[ATTR_TEMPERATURE] == 22.2 async def test_states( From f99db05a4a5477b3ef87ccb8c607234b2296cffb Mon Sep 17 00:00:00 2001 From: dontinelli <73341522+dontinelli@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:58:16 +0200 Subject: [PATCH 58/89] Add missing translation string in solarlog (#128015) --- homeassistant/components/solarlog/strings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/solarlog/strings.json b/homeassistant/components/solarlog/strings.json index 69ebbbcceda..89c41194859 100644 --- a/homeassistant/components/solarlog/strings.json +++ b/homeassistant/components/solarlog/strings.json @@ -32,7 +32,8 @@ "reconfigure_confirm": { "title": "Configure SolarLog", "data": { - "has_password": "[%key:component::solarlog::config::step::user::data::has_password%]" + "has_password": "[%key:component::solarlog::config::step::user::data::has_password%]", + "password": "[%key:common::config_flow::data::password%]" } } }, From eecdf6601331509fb7150b58ee77d2c8333e3bc4 Mon Sep 17 00:00:00 2001 From: "Steven B." <51370195+sdb9696@users.noreply.github.com> Date: Wed, 9 Oct 2024 20:23:23 +0100 Subject: [PATCH 59/89] Fix missing reauth name translation placeholder in ring integration (#128048) --- homeassistant/components/ring/config_flow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/ring/config_flow.py b/homeassistant/components/ring/config_flow.py index 8b933e8580d..d3b08210c62 100644 --- a/homeassistant/components/ring/config_flow.py +++ b/homeassistant/components/ring/config_flow.py @@ -8,7 +8,7 @@ from ring_doorbell import Auth, AuthenticationError, Requires2FAError import voluptuous as vol from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult -from homeassistant.const import CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME +from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -146,7 +146,8 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): data_schema=STEP_REAUTH_DATA_SCHEMA, errors=errors, description_placeholders={ - CONF_USERNAME: self.reauth_entry.data[CONF_USERNAME] + CONF_USERNAME: self.reauth_entry.data[CONF_USERNAME], + CONF_NAME: self.reauth_entry.data[CONF_USERNAME], }, ) From f0a653d0108dde4406612ee2fa01396712f9e9d9 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:12:00 +0200 Subject: [PATCH 60/89] Add missing translation string for re-auth flows (#128055) --- homeassistant/components/google_photos/strings.json | 3 ++- homeassistant/components/google_tasks/strings.json | 3 ++- homeassistant/components/isy994/strings.json | 3 ++- homeassistant/components/jvc_projector/strings.json | 1 + homeassistant/components/meater/strings.json | 3 ++- homeassistant/components/microbees/strings.json | 1 + homeassistant/components/risco/strings.json | 3 ++- homeassistant/components/rympro/strings.json | 3 ++- homeassistant/components/surepetcare/strings.json | 3 ++- homeassistant/components/tessie/strings.json | 3 ++- homeassistant/components/unifiprotect/strings.json | 3 ++- homeassistant/components/whirlpool/strings.json | 3 ++- homeassistant/components/withings/strings.json | 1 + 13 files changed, 23 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/google_photos/strings.json b/homeassistant/components/google_photos/strings.json index 21942ce71a7..bd565a6122d 100644 --- a/homeassistant/components/google_photos/strings.json +++ b/homeassistant/components/google_photos/strings.json @@ -21,7 +21,8 @@ "wrong_account": "Wrong account: Please authenticate with the right account.", "oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]", "oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]", - "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]" + "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" }, "create_entry": { "default": "[%key:common::config_flow::create_entry::authenticated%]" diff --git a/homeassistant/components/google_tasks/strings.json b/homeassistant/components/google_tasks/strings.json index 447da5e24c2..a26cf8c58ec 100644 --- a/homeassistant/components/google_tasks/strings.json +++ b/homeassistant/components/google_tasks/strings.json @@ -21,7 +21,8 @@ "wrong_account": "Wrong account: Please authenticate with the right account.", "oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]", "oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]", - "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]" + "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" }, "create_entry": { "default": "[%key:common::config_flow::create_entry::authenticated%]" diff --git a/homeassistant/components/isy994/strings.json b/homeassistant/components/isy994/strings.json index ec7d78edd53..f0e55881652 100644 --- a/homeassistant/components/isy994/strings.json +++ b/homeassistant/components/isy994/strings.json @@ -29,7 +29,8 @@ "invalid_host": "The host entry was not in full URL format, e.g., http://192.168.10.100:80" }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, "options": { diff --git a/homeassistant/components/jvc_projector/strings.json b/homeassistant/components/jvc_projector/strings.json index b89139cbab3..b517bf064e1 100644 --- a/homeassistant/components/jvc_projector/strings.json +++ b/homeassistant/components/jvc_projector/strings.json @@ -24,6 +24,7 @@ "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", "unknown": "[%key:common::config_flow::error::unknown%]" }, "error": { diff --git a/homeassistant/components/meater/strings.json b/homeassistant/components/meater/strings.json index 279841bb147..20dd2919026 100644 --- a/homeassistant/components/meater/strings.json +++ b/homeassistant/components/meater/strings.json @@ -19,7 +19,8 @@ } }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_account%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" }, "error": { "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", diff --git a/homeassistant/components/microbees/strings.json b/homeassistant/components/microbees/strings.json index 49d42af83d3..8635753a564 100644 --- a/homeassistant/components/microbees/strings.json +++ b/homeassistant/components/microbees/strings.json @@ -21,6 +21,7 @@ "no_url_available": "[%key:common::config_flow::abort::oauth2_no_url_available%]", "user_rejected_authorize": "[%key:common::config_flow::abort::oauth2_user_rejected_authorize%]", "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", "unknown": "[%key:common::config_flow::error::unknown%]", "wrong_account": "You can only reauthenticate this entry with the same microBees account." }, diff --git a/homeassistant/components/risco/strings.json b/homeassistant/components/risco/strings.json index e35b13394cb..86d131b4f80 100644 --- a/homeassistant/components/risco/strings.json +++ b/homeassistant/components/risco/strings.json @@ -28,7 +28,8 @@ "unknown": "[%key:common::config_flow::error::unknown%]" }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, "options": { diff --git a/homeassistant/components/rympro/strings.json b/homeassistant/components/rympro/strings.json index c58bf5b93ba..2c1e2ad93c9 100644 --- a/homeassistant/components/rympro/strings.json +++ b/homeassistant/components/rympro/strings.json @@ -14,7 +14,8 @@ "unknown": "[%key:common::config_flow::error::unknown%]" }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, "entity": { diff --git a/homeassistant/components/surepetcare/strings.json b/homeassistant/components/surepetcare/strings.json index c3b7864f36a..58db669732a 100644 --- a/homeassistant/components/surepetcare/strings.json +++ b/homeassistant/components/surepetcare/strings.json @@ -21,7 +21,8 @@ "unknown": "[%key:common::config_flow::error::unknown%]" }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_account%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, "services": { diff --git a/homeassistant/components/tessie/strings.json b/homeassistant/components/tessie/strings.json index 52c03c8700b..336a6b9404c 100644 --- a/homeassistant/components/tessie/strings.json +++ b/homeassistant/components/tessie/strings.json @@ -1,7 +1,8 @@ { "config": { "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_service%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" }, "error": { "invalid_access_token": "[%key:common::config_flow::error::invalid_access_token%]", diff --git a/homeassistant/components/unifiprotect/strings.json b/homeassistant/components/unifiprotect/strings.json index aaef111a351..9238c825390 100644 --- a/homeassistant/components/unifiprotect/strings.json +++ b/homeassistant/components/unifiprotect/strings.json @@ -42,7 +42,8 @@ }, "abort": { "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "discovery_started": "Discovery started" + "discovery_started": "Discovery started", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } }, "options": { diff --git a/homeassistant/components/whirlpool/strings.json b/homeassistant/components/whirlpool/strings.json index 4b4673b771e..09257652ece 100644 --- a/homeassistant/components/whirlpool/strings.json +++ b/homeassistant/components/whirlpool/strings.json @@ -27,7 +27,8 @@ } }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_account%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", diff --git a/homeassistant/components/withings/strings.json b/homeassistant/components/withings/strings.json index b7da59eda4c..5e5f18aeab8 100644 --- a/homeassistant/components/withings/strings.json +++ b/homeassistant/components/withings/strings.json @@ -21,6 +21,7 @@ "oauth_timeout": "[%key:common::config_flow::abort::oauth2_timeout%]", "oauth_unauthorized": "[%key:common::config_flow::abort::oauth2_unauthorized%]", "oauth_failed": "[%key:common::config_flow::abort::oauth2_failed%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", "wrong_account": "Authenticated account does not match the account to be reauthenticated. Please log in with the correct account." }, "create_entry": { From a3475607b216a1cfa5c6c2cdea7f3a6a1cc8ab14 Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Fri, 11 Oct 2024 12:50:15 +0200 Subject: [PATCH 61/89] Update xknxproject to 3.8.1 (#128057) --- homeassistant/components/knx/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/knx/manifest.json b/homeassistant/components/knx/manifest.json index aa0178b2c4a..a3b9f29e01d 100644 --- a/homeassistant/components/knx/manifest.json +++ b/homeassistant/components/knx/manifest.json @@ -12,7 +12,7 @@ "quality_scale": "platinum", "requirements": [ "xknx==3.2.0", - "xknxproject==3.8.0", + "xknxproject==3.8.1", "knx-frontend==2024.9.10.221729" ], "single_config_entry": true diff --git a/requirements_all.txt b/requirements_all.txt index 791d1e1faa2..4e6b8549976 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2992,7 +2992,7 @@ xiaomi-ble==0.32.0 xknx==3.2.0 # homeassistant.components.knx -xknxproject==3.8.0 +xknxproject==3.8.1 # homeassistant.components.fritz # homeassistant.components.rest diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ca0008d8866..872f1a2ce6f 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2381,7 +2381,7 @@ xiaomi-ble==0.32.0 xknx==3.2.0 # homeassistant.components.knx -xknxproject==3.8.0 +xknxproject==3.8.1 # homeassistant.components.fritz # homeassistant.components.rest From 571bfaf5d7862eb1296249d94e021c028069e961 Mon Sep 17 00:00:00 2001 From: kingy444 Date: Thu, 10 Oct 2024 23:22:14 +1100 Subject: [PATCH 62/89] Fix casing on Powerview Gen3 zeroconf discovery (#128076) --- .../components/hunterdouglas_powerview/config_flow.py | 2 +- .../components/hunterdouglas_powerview/manifest.json | 2 +- homeassistant/generated/zeroconf.py | 10 +++++----- tests/components/hunterdouglas_powerview/const.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/hunterdouglas_powerview/config_flow.py b/homeassistant/components/hunterdouglas_powerview/config_flow.py index 88ccf890c66..aaa74473dd9 100644 --- a/homeassistant/components/hunterdouglas_powerview/config_flow.py +++ b/homeassistant/components/hunterdouglas_powerview/config_flow.py @@ -23,7 +23,7 @@ _LOGGER = logging.getLogger(__name__) HAP_SUFFIX = "._hap._tcp.local." POWERVIEW_G2_SUFFIX = "._powerview._tcp.local." -POWERVIEW_G3_SUFFIX = "._powerview-g3._tcp.local." +POWERVIEW_G3_SUFFIX = "._PowerView-G3._tcp.local." async def validate_input(hass: HomeAssistant, hub_address: str) -> dict[str, str]: diff --git a/homeassistant/components/hunterdouglas_powerview/manifest.json b/homeassistant/components/hunterdouglas_powerview/manifest.json index 4120c55a7a7..a80708d9a3f 100644 --- a/homeassistant/components/hunterdouglas_powerview/manifest.json +++ b/homeassistant/components/hunterdouglas_powerview/manifest.json @@ -19,5 +19,5 @@ "iot_class": "local_polling", "loggers": ["aiopvapi"], "requirements": ["aiopvapi==3.1.1"], - "zeroconf": ["_powerview._tcp.local.", "_powerview-g3._tcp.local."] + "zeroconf": ["_powerview._tcp.local.", "_PowerView-G3._tcp.local."] } diff --git a/homeassistant/generated/zeroconf.py b/homeassistant/generated/zeroconf.py index f627f1f0f47..a2d9b663cec 100644 --- a/homeassistant/generated/zeroconf.py +++ b/homeassistant/generated/zeroconf.py @@ -267,6 +267,11 @@ HOMEKIT = { } ZEROCONF = { + "_PowerView-G3._tcp.local.": [ + { + "domain": "hunterdouglas_powerview", + }, + ], "_Volumio._tcp.local.": [ { "domain": "volumio", @@ -695,11 +700,6 @@ ZEROCONF = { "domain": "plugwise", }, ], - "_powerview-g3._tcp.local.": [ - { - "domain": "hunterdouglas_powerview", - }, - ], "_powerview._tcp.local.": [ { "domain": "hunterdouglas_powerview", diff --git a/tests/components/hunterdouglas_powerview/const.py b/tests/components/hunterdouglas_powerview/const.py index 5a912a63a17..db8adc57e5a 100644 --- a/tests/components/hunterdouglas_powerview/const.py +++ b/tests/components/hunterdouglas_powerview/const.py @@ -41,7 +41,7 @@ ZEROCONF_DISCOVERY_GEN3 = zeroconf.ZeroconfServiceInfo( ip_address="1.2.3.4", ip_addresses=[IPv4Address("1.2.3.4")], hostname="mock_hostname", - name="Powerview Generation 3._powerview-g3._tcp.local.", + name="Powerview Generation 3._PowerView-G3._tcp.local.", port=None, properties={}, type="mock_type", From ee9525cc00f7b6c16a2494d5368f1e541ab98c37 Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Fri, 11 Oct 2024 16:17:32 +0100 Subject: [PATCH 63/89] Fix ring realtime events (#128083) --- homeassistant/components/ring/__init__.py | 46 ++++++++++------- homeassistant/components/ring/config_flow.py | 41 ++++++++++++--- homeassistant/components/ring/const.py | 3 ++ tests/components/ring/conftest.py | 8 ++- tests/components/ring/test_config_flow.py | 52 +++++++++++--------- tests/components/ring/test_init.py | 34 ++++++++++++- 6 files changed, 135 insertions(+), 49 deletions(-) diff --git a/homeassistant/components/ring/__init__.py b/homeassistant/components/ring/__init__.py index c1042a9546d..b2340b34556 100644 --- a/homeassistant/components/ring/__init__.py +++ b/homeassistant/components/ring/__init__.py @@ -10,13 +10,9 @@ import uuid from ring_doorbell import Auth, Ring, RingDevices from homeassistant.config_entries import ConfigEntry -from homeassistant.const import APPLICATION_NAME, CONF_TOKEN +from homeassistant.const import APPLICATION_NAME, CONF_DEVICE_ID, CONF_TOKEN from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers import ( - device_registry as dr, - entity_registry as er, - instance_id, -) +from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.aiohttp_client import async_get_clientsession from .const import CONF_LISTEN_CREDENTIALS, DOMAIN, PLATFORMS @@ -38,18 +34,12 @@ class RingData: type RingConfigEntry = ConfigEntry[RingData] -async def get_auth_agent_id(hass: HomeAssistant) -> tuple[str, str]: - """Return user-agent and hardware id for Auth instantiation. +def get_auth_user_agent() -> str: + """Return user-agent for Auth instantiation. user_agent will be the display name in the ring.com authorised devices. - hardware_id will uniquely describe the authorised HA device. """ - user_agent = f"{APPLICATION_NAME}/{DOMAIN}-integration" - - # Generate a new uuid from the instance_uuid to keep the HA one private - instance_uuid = uuid.UUID(hex=await instance_id.async_get(hass)) - hardware_id = str(uuid.uuid5(instance_uuid, user_agent)) - return user_agent, hardware_id + return f"{APPLICATION_NAME}/{DOMAIN}-integration" async def async_setup_entry(hass: HomeAssistant, entry: RingConfigEntry) -> bool: @@ -69,13 +59,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: RingConfigEntry) -> bool data={**entry.data, CONF_LISTEN_CREDENTIALS: token}, ) - user_agent, hardware_id = await get_auth_agent_id(hass) + user_agent = get_auth_user_agent() client_session = async_get_clientsession(hass) auth = Auth( user_agent, entry.data[CONF_TOKEN], token_updater, - hardware_id=hardware_id, + hardware_id=entry.data[CONF_DEVICE_ID], http_client_session=client_session, ) ring = Ring(auth) @@ -138,3 +128,25 @@ async def _migrate_old_unique_ids(hass: HomeAssistant, entry_id: str) -> None: return None await er.async_migrate_entries(hass, entry_id, _async_migrator) + + +async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Migrate old config entry.""" + entry_version = entry.version + entry_minor_version = entry.minor_version + + new_minor_version = 2 + if entry_version == 1 and entry_minor_version == 1: + _LOGGER.debug( + "Migrating from version %s.%s", entry_version, entry_minor_version + ) + hardware_id = str(uuid.uuid4()) + hass.config_entries.async_update_entry( + entry, + data={**entry.data, CONF_DEVICE_ID: hardware_id}, + minor_version=new_minor_version, + ) + _LOGGER.debug( + "Migration to version %s.%s complete", entry_version, new_minor_version + ) + return True diff --git a/homeassistant/components/ring/config_flow.py b/homeassistant/components/ring/config_flow.py index d3b08210c62..abeaea07171 100644 --- a/homeassistant/components/ring/config_flow.py +++ b/homeassistant/components/ring/config_flow.py @@ -3,18 +3,25 @@ from collections.abc import Mapping import logging from typing import Any +import uuid from ring_doorbell import Auth, AuthenticationError, Requires2FAError import voluptuous as vol from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult -from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME +from homeassistant.const import ( + CONF_DEVICE_ID, + CONF_NAME, + CONF_PASSWORD, + CONF_TOKEN, + CONF_USERNAME, +) from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.aiohttp_client import async_get_clientsession -from . import get_auth_agent_id -from .const import CONF_2FA, DOMAIN +from . import get_auth_user_agent +from .const import CONF_2FA, CONF_CONFIG_ENTRY_MINOR_VERSION, DOMAIN _LOGGER = logging.getLogger(__name__) @@ -23,11 +30,15 @@ STEP_USER_DATA_SCHEMA = vol.Schema( ) STEP_REAUTH_DATA_SCHEMA = vol.Schema({vol.Required(CONF_PASSWORD): str}) +STEP_RECONFIGURE_DATA_SCHEMA = vol.Schema({vol.Required(CONF_PASSWORD): str}) -async def validate_input(hass: HomeAssistant, data: dict[str, str]) -> dict[str, Any]: + +async def validate_input( + hass: HomeAssistant, hardware_id: str, data: dict[str, str] +) -> dict[str, Any]: """Validate the user input allows us to connect.""" - user_agent, hardware_id = await get_auth_agent_id(hass) + user_agent = get_auth_user_agent() auth = Auth( user_agent, http_client_session=async_get_clientsession(hass), @@ -52,8 +63,10 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for Ring.""" VERSION = 1 + MINOR_VERSION = CONF_CONFIG_ENTRY_MINOR_VERSION user_pass: dict[str, Any] = {} + hardware_id: str | None = None reauth_entry: ConfigEntry | None = None async def async_step_user( @@ -64,8 +77,10 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): if user_input is not None: await self.async_set_unique_id(user_input[CONF_USERNAME]) self._abort_if_unique_id_configured() + if not self.hardware_id: + self.hardware_id = str(uuid.uuid4()) try: - token = await validate_input(self.hass, user_input) + token = await validate_input(self.hass, self.hardware_id, user_input) except Require2FA: self.user_pass = user_input @@ -78,7 +93,11 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): else: return self.async_create_entry( title=user_input[CONF_USERNAME], - data={CONF_USERNAME: user_input[CONF_USERNAME], CONF_TOKEN: token}, + data={ + CONF_DEVICE_ID: self.hardware_id, + CONF_USERNAME: user_input[CONF_USERNAME], + CONF_TOKEN: token, + }, ) return self.async_show_form( @@ -120,8 +139,13 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): if user_input: user_input[CONF_USERNAME] = self.reauth_entry.data[CONF_USERNAME] + # Reauth will use the same hardware id and re-authorise an existing + # authorised device. + if not self.hardware_id: + self.hardware_id = self.reauth_entry.data[CONF_DEVICE_ID] + assert self.hardware_id try: - token = await validate_input(self.hass, user_input) + token = await validate_input(self.hass, self.hardware_id, user_input) except Require2FA: self.user_pass = user_input return await self.async_step_2fa() @@ -134,6 +158,7 @@ class RingConfigFlow(ConfigFlow, domain=DOMAIN): data = { CONF_USERNAME: user_input[CONF_USERNAME], CONF_TOKEN: token, + CONF_DEVICE_ID: self.hardware_id, } self.hass.config_entries.async_update_entry( self.reauth_entry, data=data diff --git a/homeassistant/components/ring/const.py b/homeassistant/components/ring/const.py index 24801045b17..9595241ebb1 100644 --- a/homeassistant/components/ring/const.py +++ b/homeassistant/components/ring/const.py @@ -3,6 +3,7 @@ from __future__ import annotations from datetime import timedelta +from typing import Final from homeassistant.const import Platform @@ -31,3 +32,5 @@ SCAN_INTERVAL = timedelta(minutes=1) CONF_2FA = "2fa" CONF_LISTEN_CREDENTIALS = "listen_token" + +CONF_CONFIG_ENTRY_MINOR_VERSION: Final = 2 diff --git a/tests/components/ring/conftest.py b/tests/components/ring/conftest.py index 90f2fd2a956..1296c2f58c5 100644 --- a/tests/components/ring/conftest.py +++ b/tests/components/ring/conftest.py @@ -8,7 +8,8 @@ import pytest import ring_doorbell from homeassistant.components.ring import DOMAIN -from homeassistant.const import CONF_USERNAME +from homeassistant.components.ring.const import CONF_CONFIG_ENTRY_MINOR_VERSION +from homeassistant.const import CONF_DEVICE_ID, CONF_USERNAME from homeassistant.core import HomeAssistant from .device_mocks import get_devices_data, get_mock_devices @@ -16,6 +17,8 @@ from .device_mocks import get_devices_data, get_mock_devices from tests.common import MockConfigEntry from tests.components.light.conftest import mock_light_profiles # noqa: F401 +MOCK_HARDWARE_ID = "foo-bar" + @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock]: @@ -116,10 +119,13 @@ def mock_config_entry() -> MockConfigEntry: title="Ring", domain=DOMAIN, data={ + CONF_DEVICE_ID: MOCK_HARDWARE_ID, CONF_USERNAME: "foo@bar.com", "token": {"access_token": "mock-token"}, }, unique_id="foo@bar.com", + version=1, + minor_version=CONF_CONFIG_ENTRY_MINOR_VERSION, ) diff --git a/tests/components/ring/test_config_flow.py b/tests/components/ring/test_config_flow.py index d27c4878aea..d13a78538bb 100644 --- a/tests/components/ring/test_config_flow.py +++ b/tests/components/ring/test_config_flow.py @@ -1,16 +1,18 @@ """Test the Ring config flow.""" -from unittest.mock import AsyncMock, Mock +from unittest.mock import AsyncMock, Mock, patch import pytest import ring_doorbell from homeassistant import config_entries from homeassistant.components.ring import DOMAIN -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.const import CONF_DEVICE_ID, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResultType +from .conftest import MOCK_HARDWARE_ID + from tests.common import MockConfigEntry @@ -27,17 +29,19 @@ async def test_form( assert result["type"] is FlowResultType.FORM assert result["errors"] == {} - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - {"username": "hello@home-assistant.io", "password": "test-password"}, - ) - await hass.async_block_till_done() + with patch("uuid.uuid4", return_value=MOCK_HARDWARE_ID): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + {"username": "hello@home-assistant.io", "password": "test-password"}, + ) + await hass.async_block_till_done() assert result2["type"] is FlowResultType.CREATE_ENTRY assert result2["title"] == "hello@home-assistant.io" assert result2["data"] == { - "username": "hello@home-assistant.io", - "token": {"access_token": "mock-token"}, + CONF_DEVICE_ID: MOCK_HARDWARE_ID, + CONF_USERNAME: "hello@home-assistant.io", + CONF_TOKEN: {"access_token": "mock-token"}, } assert len(mock_setup_entry.mock_calls) == 1 @@ -80,13 +84,14 @@ async def test_form_2fa( assert result["errors"] == {} mock_ring_auth.async_fetch_token.side_effect = ring_doorbell.Requires2FAError - result2 = await hass.config_entries.flow.async_configure( - result["flow_id"], - { - CONF_USERNAME: "foo@bar.com", - CONF_PASSWORD: "fake-password", - }, - ) + with patch("uuid.uuid4", return_value=MOCK_HARDWARE_ID): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_USERNAME: "foo@bar.com", + CONF_PASSWORD: "fake-password", + }, + ) await hass.async_block_till_done() mock_ring_auth.async_fetch_token.assert_called_once_with( "foo@bar.com", "fake-password", None @@ -107,8 +112,9 @@ async def test_form_2fa( assert result3["type"] is FlowResultType.CREATE_ENTRY assert result3["title"] == "foo@bar.com" assert result3["data"] == { - "username": "foo@bar.com", - "token": "new-foobar", + CONF_DEVICE_ID: MOCK_HARDWARE_ID, + CONF_USERNAME: "foo@bar.com", + CONF_TOKEN: "new-foobar", } assert len(mock_setup_entry.mock_calls) == 1 @@ -154,8 +160,9 @@ async def test_reauth( assert result3["type"] is FlowResultType.ABORT assert result3["reason"] == "reauth_successful" assert mock_added_config_entry.data == { - "username": "foo@bar.com", - "token": "new-foobar", + CONF_DEVICE_ID: MOCK_HARDWARE_ID, + CONF_USERNAME: "foo@bar.com", + CONF_TOKEN: "new-foobar", } assert len(mock_setup_entry.mock_calls) == 1 @@ -216,8 +223,9 @@ async def test_reauth_error( assert result3["type"] is FlowResultType.ABORT assert result3["reason"] == "reauth_successful" assert mock_added_config_entry.data == { - "username": "foo@bar.com", - "token": "new-foobar", + CONF_DEVICE_ID: MOCK_HARDWARE_ID, + CONF_USERNAME: "foo@bar.com", + CONF_TOKEN: "new-foobar", } assert len(mock_setup_entry.mock_calls) == 1 diff --git a/tests/components/ring/test_init.py b/tests/components/ring/test_init.py index 5ac9e444cca..1b5ee68c659 100644 --- a/tests/components/ring/test_init.py +++ b/tests/components/ring/test_init.py @@ -1,5 +1,7 @@ """The tests for the Ring component.""" +from unittest.mock import AsyncMock, patch + from freezegun.api import FrozenDateTimeFactory import pytest from ring_doorbell import AuthenticationError, Ring, RingError, RingTimeout @@ -12,11 +14,12 @@ from homeassistant.components.ring import DOMAIN from homeassistant.components.ring.const import CONF_LISTEN_CREDENTIALS, SCAN_INTERVAL from homeassistant.components.ring.coordinator import RingEventListener from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState -from homeassistant.const import CONF_TOKEN, CONF_USERNAME +from homeassistant.const import CONF_DEVICE_ID, CONF_TOKEN, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component +from .conftest import MOCK_HARDWARE_ID from .device_mocks import FRONT_DOOR_DEVICE_ID from tests.common import MockConfigEntry, async_fire_time_changed @@ -450,3 +453,32 @@ async def test_no_listen_start( assert "Ring event listener failed to start after 10 seconds" in [ record.message for record in caplog.records if record.levelname == "WARNING" ] + + +async def test_migrate_create_device_id( + hass: HomeAssistant, + mock_setup_entry: AsyncMock, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test migration creates new device id created.""" + entry = MockConfigEntry( + title="Ring", + domain=DOMAIN, + data={ + CONF_USERNAME: "foo@bar.com", + "token": {"access_token": "mock-token"}, + }, + unique_id="foo@bar.com", + version=1, + minor_version=1, + ) + entry.add_to_hass(hass) + with patch("uuid.uuid4", return_value=MOCK_HARDWARE_ID): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.minor_version == 2 + assert CONF_DEVICE_ID in entry.data + assert entry.data[CONF_DEVICE_ID] == MOCK_HARDWARE_ID + + assert "Migration to version 1.2 complete" in caplog.text From 92b67ead831ae39242e642d128577879c9b5b5a9 Mon Sep 17 00:00:00 2001 From: David Knowles Date: Thu, 10 Oct 2024 10:35:33 -0400 Subject: [PATCH 64/89] Increase Hydrawise polling interval to 60 seconds (#128090) --- homeassistant/components/hydrawise/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/hydrawise/const.py b/homeassistant/components/hydrawise/const.py index f731ecf278c..47b9bef845e 100644 --- a/homeassistant/components/hydrawise/const.py +++ b/homeassistant/components/hydrawise/const.py @@ -10,7 +10,7 @@ DEFAULT_WATERING_TIME = timedelta(minutes=15) MANUFACTURER = "Hydrawise" -SCAN_INTERVAL = timedelta(seconds=30) +SCAN_INTERVAL = timedelta(seconds=60) SIGNAL_UPDATE_HYDRAWISE = "hydrawise_update" From 9cfc9b9bafded0ff7505bea165cb18837528eca7 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 10 Oct 2024 19:14:20 +0200 Subject: [PATCH 65/89] Update frontend to 20241002.3 (#128106) --- 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 9f79dcf34f6..80119002be5 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20241002.2"] + "requirements": ["home-assistant-frontend==20241002.3"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 1da76f572a1..159463e8928 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -32,7 +32,7 @@ habluetooth==3.4.0 hass-nabucasa==0.81.1 hassil==1.7.4 home-assistant-bluetooth==1.12.2 -home-assistant-frontend==20241002.2 +home-assistant-frontend==20241002.3 home-assistant-intents==2024.10.2 httpx==0.27.2 ifaddr==0.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index 4e6b8549976..b7989892cd4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1117,7 +1117,7 @@ hole==0.8.0 holidays==0.58 # homeassistant.components.frontend -home-assistant-frontend==20241002.2 +home-assistant-frontend==20241002.3 # homeassistant.components.conversation home-assistant-intents==2024.10.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 872f1a2ce6f..604cab1f200 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -943,7 +943,7 @@ hole==0.8.0 holidays==0.58 # homeassistant.components.frontend -home-assistant-frontend==20241002.2 +home-assistant-frontend==20241002.3 # homeassistant.components.conversation home-assistant-intents==2024.10.2 From 3e2edc1a2dff76a31af7006007dbc36d71776051 Mon Sep 17 00:00:00 2001 From: Thomas55555 <59625598+Thomas55555@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:43:01 +0200 Subject: [PATCH 66/89] Bump aioautomower to 2024.10.0 (#128137) Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- homeassistant/components/husqvarna_automower/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/husqvarna_automower/manifest.json b/homeassistant/components/husqvarna_automower/manifest.json index 85acfaf66a2..17d32c270d9 100644 --- a/homeassistant/components/husqvarna_automower/manifest.json +++ b/homeassistant/components/husqvarna_automower/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/husqvarna_automower", "iot_class": "cloud_push", "loggers": ["aioautomower"], - "requirements": ["aioautomower==2024.9.3"] + "requirements": ["aioautomower==2024.10.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index b7989892cd4..4672b2800d5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -198,7 +198,7 @@ aioaseko==1.0.0 aioasuswrt==1.4.0 # homeassistant.components.husqvarna_automower -aioautomower==2024.9.3 +aioautomower==2024.10.0 # homeassistant.components.azure_devops aioazuredevops==2.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 604cab1f200..fa274b59c56 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -186,7 +186,7 @@ aioaseko==1.0.0 aioasuswrt==1.4.0 # homeassistant.components.husqvarna_automower -aioautomower==2024.9.3 +aioautomower==2024.10.0 # homeassistant.components.azure_devops aioazuredevops==2.2.1 From 773564d4f541cd4eb0de8bb37700391376261661 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:59:43 +0200 Subject: [PATCH 67/89] Fix license script for ftfy (#128138) --- .github/workflows/ci.yaml | 2 +- script/licenses.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 00eda06042c..2a17e0b2d42 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,7 +37,7 @@ on: type: boolean env: - CACHE_VERSION: 10 + CACHE_VERSION: 11 UV_CACHE_VERSION: 1 MYPY_CACHE_VERSION: 9 HA_SHORT_VERSION: "2024.10" diff --git a/script/licenses.py b/script/licenses.py index f39dcf13c14..b04b3cd2726 100644 --- a/script/licenses.py +++ b/script/licenses.py @@ -165,6 +165,8 @@ EXCEPTIONS = { "tapsaff", # https://github.com/bazwilliams/python-taps-aff/pull/5 "vincenty", # Public domain "zeversolar", # https://github.com/kvanzuijlen/zeversolar/pull/46 + # Using License-Expression (with hatchling) + "ftfy", # Apache-2.0 } TODO = { From 7aec98dafd89d41b72ad5d64e92907011460750e Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 11 Oct 2024 03:10:07 -0700 Subject: [PATCH 68/89] Fix regression in Opower that was introduced in 2024.10.0 (#128141) * Avoid KeyError when statistics have gaps * fix break * Remove unnecessary check --- .../components/opower/coordinator.py | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/opower/coordinator.py b/homeassistant/components/opower/coordinator.py index cd2e28ed638..3b4cd07590c 100644 --- a/homeassistant/components/opower/coordinator.py +++ b/homeassistant/components/opower/coordinator.py @@ -130,19 +130,41 @@ class OpowerCoordinator(DataUpdateCoordinator[dict[str, Forecast]]): continue start = cost_reads[0].start_time _LOGGER.debug("Getting statistics at: %s", start) - stats = await get_instance(self.hass).async_add_executor_job( - statistics_during_period, - self.hass, - start, - start + timedelta(seconds=1), - {cost_statistic_id, consumption_statistic_id}, - "hour", - None, - {"sum"}, - ) + # In the common case there should be a previous statistic at start time + # so we only need to fetch one statistic. If there isn't any, fetch all. + for end in (start + timedelta(seconds=1), None): + stats = await get_instance(self.hass).async_add_executor_job( + statistics_during_period, + self.hass, + start, + end, + {cost_statistic_id, consumption_statistic_id}, + "hour", + None, + {"sum"}, + ) + if stats: + break + if end: + _LOGGER.debug( + "Not found. Trying to find the oldest statistic after %s", + start, + ) + # We are in this code path only if get_last_statistics found a stat + # so statistics_during_period should also have found at least one. + assert stats cost_sum = cast(float, stats[cost_statistic_id][0]["sum"]) consumption_sum = cast(float, stats[consumption_statistic_id][0]["sum"]) last_stats_time = stats[consumption_statistic_id][0]["start"] + if end is None: + # If there was no statistic at the start of the cost reads, + # ignore cost reads past the last_stats_time. + cost_reads = [ + cost_read + for cost_read in cost_reads + if cost_read.start_time.timestamp() >= last_stats_time + ] + start = cost_reads[0].start_time assert last_stats_time == start.timestamp() cost_statistics = [] From f5d04a970f4a80cf53386a24c56396dc8e54a49e Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 11 Oct 2024 03:02:11 -0700 Subject: [PATCH 69/89] Bump opower to 0.8.3 (#128144) --- homeassistant/components/opower/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opower/manifest.json b/homeassistant/components/opower/manifest.json index 23386a777d2..6c78dc5229c 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", "loggers": ["opower"], - "requirements": ["opower==0.8.2"] + "requirements": ["opower==0.8.3"] } diff --git a/requirements_all.txt b/requirements_all.txt index 4672b2800d5..4818ded19dc 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1544,7 +1544,7 @@ openwrt-luci-rpc==1.1.17 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.8.2 +opower==0.8.3 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fa274b59c56..ed42a88ef62 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1274,7 +1274,7 @@ openhomedevice==2.2.0 openwebifpy==4.2.7 # homeassistant.components.opower -opower==0.8.2 +opower==0.8.3 # homeassistant.components.oralb oralb-ble==0.17.6 From a8836ca7b64362024d99734b20f47f996577f793 Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 11 Oct 2024 03:37:23 -0700 Subject: [PATCH 70/89] Remove some redundant code in Opower's coordinator from the fix in #128141 (#128150) --- homeassistant/components/opower/coordinator.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/homeassistant/components/opower/coordinator.py b/homeassistant/components/opower/coordinator.py index 3b4cd07590c..629dce0823c 100644 --- a/homeassistant/components/opower/coordinator.py +++ b/homeassistant/components/opower/coordinator.py @@ -156,16 +156,6 @@ class OpowerCoordinator(DataUpdateCoordinator[dict[str, Forecast]]): cost_sum = cast(float, stats[cost_statistic_id][0]["sum"]) consumption_sum = cast(float, stats[consumption_statistic_id][0]["sum"]) last_stats_time = stats[consumption_statistic_id][0]["start"] - if end is None: - # If there was no statistic at the start of the cost reads, - # ignore cost reads past the last_stats_time. - cost_reads = [ - cost_read - for cost_read in cost_reads - if cost_read.start_time.timestamp() >= last_stats_time - ] - start = cost_reads[0].start_time - assert last_stats_time == start.timestamp() cost_statistics = [] consumption_statistics = [] From 0ccff9fc54ba1af846bd6b3fee824f6560713aac Mon Sep 17 00:00:00 2001 From: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:15:16 +0200 Subject: [PATCH 71/89] Fix preset handling issue in ViCare (#128167) * add test case * fix test case * fix issue * change order --- homeassistant/components/vicare/types.py | 9 +++++++-- tests/components/vicare/test_types.py | 13 ++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/vicare/types.py b/homeassistant/components/vicare/types.py index 7e1ec7f8bee..dc105a86aa9 100644 --- a/homeassistant/components/vicare/types.py +++ b/homeassistant/components/vicare/types.py @@ -1,6 +1,7 @@ """Types for the ViCare integration.""" from collections.abc import Callable +from contextlib import suppress from dataclasses import dataclass import enum from typing import Any @@ -48,8 +49,12 @@ class HeatingProgram(enum.StrEnum): ) -> str | None: """Return the mapped ViCare heating program for the Home Assistant preset.""" for program in supported_heating_programs: - if VICARE_TO_HA_PRESET_HEATING.get(HeatingProgram(program)) == ha_preset: - return program + with suppress(ValueError): + if ( + VICARE_TO_HA_PRESET_HEATING.get(HeatingProgram(program)) + == ha_preset + ): + return program return None diff --git a/tests/components/vicare/test_types.py b/tests/components/vicare/test_types.py index 13d8255cf8d..c411213f13e 100644 --- a/tests/components/vicare/test_types.py +++ b/tests/components/vicare/test_types.py @@ -39,7 +39,7 @@ async def test_ha_preset_to_heating_program( ha_preset: str | None, expected_result: str | None, ) -> None: - """Testing HA Preset tp ViCare HeatingProgram.""" + """Testing HA Preset to ViCare HeatingProgram.""" supported_programs = [ HeatingProgram.COMFORT, @@ -52,6 +52,17 @@ async def test_ha_preset_to_heating_program( ) +async def test_ha_preset_to_heating_program_error() -> None: + """Testing HA Preset to ViCare HeatingProgram.""" + + supported_programs = [ + "test", + ] + assert ( + HeatingProgram.from_ha_preset(HeatingProgram.NORMAL, supported_programs) is None + ) + + @pytest.mark.parametrize( ("vicare_mode", "expected_result"), [ From d389b55f40d8b67a8831e9ac553d295c3cf28780 Mon Sep 17 00:00:00 2001 From: Thomas55555 <59625598+Thomas55555@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:05:13 +0200 Subject: [PATCH 72/89] Fix model in Husqvarna Automower (#128168) --- homeassistant/components/husqvarna_automower/entity.py | 4 +++- tests/components/husqvarna_automower/snapshots/test_init.ambr | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/husqvarna_automower/entity.py b/homeassistant/components/husqvarna_automower/entity.py index fd9e7578fb2..6ce17926cfe 100644 --- a/homeassistant/components/husqvarna_automower/entity.py +++ b/homeassistant/components/husqvarna_automower/entity.py @@ -125,7 +125,9 @@ class AutomowerBaseEntity(CoordinatorEntity[AutomowerDataUpdateCoordinator]): self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, mower_id)}, manufacturer="Husqvarna", - model=self.mower_attributes.system.model, + model=self.mower_attributes.system.model.removeprefix( + "HUSQVARNA " + ).removeprefix("Husqvarna "), name=self.mower_attributes.system.name, serial_number=self.mower_attributes.system.serial_number, suggested_area="Garden", diff --git a/tests/components/husqvarna_automower/snapshots/test_init.ambr b/tests/components/husqvarna_automower/snapshots/test_init.ambr index adf70fb0aab..e79bd1f8145 100644 --- a/tests/components/husqvarna_automower/snapshots/test_init.ambr +++ b/tests/components/husqvarna_automower/snapshots/test_init.ambr @@ -20,7 +20,7 @@ 'labels': set({ }), 'manufacturer': 'Husqvarna', - 'model': 'HUSQVARNA AUTOMOWER® 450XH', + 'model': 'AUTOMOWER® 450XH', 'model_id': None, 'name': 'Test Mower 1', 'name_by_user': None, From 9176994947c94a78382670f16b6e23140d80cb95 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 11 Oct 2024 17:54:37 +0200 Subject: [PATCH 73/89] Bump version to 2024.10.2 --- 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 26049ed326b..b539cbc6068 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2024 MINOR_VERSION: Final = 10 -PATCH_VERSION: Final = "1" +PATCH_VERSION: Final = "2" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 12, 0) diff --git a/pyproject.toml b/pyproject.toml index 955aac83f36..a79ffb0fe57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2024.10.1" +version = "2024.10.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From 18d65d513e100f433b7888a7eb7245abe8bb8f37 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sun, 6 Oct 2024 02:15:05 +0200 Subject: [PATCH 74/89] Update home-assistant-bluetooth to 1.13.0 (#127691) --- homeassistant/package_constraints.txt | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 159463e8928..a05c932b0f1 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -31,7 +31,7 @@ ha-ffmpeg==3.2.0 habluetooth==3.4.0 hass-nabucasa==0.81.1 hassil==1.7.4 -home-assistant-bluetooth==1.12.2 +home-assistant-bluetooth==1.13.0 home-assistant-frontend==20241002.3 home-assistant-intents==2024.10.2 httpx==0.27.2 diff --git a/pyproject.toml b/pyproject.toml index a79ffb0fe57..5eb72a2b40e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ dependencies = [ # When bumping httpx, please check the version pins of # httpcore, anyio, and h11 in gen_requirements_all "httpx==0.27.2", - "home-assistant-bluetooth==1.12.2", + "home-assistant-bluetooth==1.13.0", "ifaddr==0.2.0", "Jinja2==3.1.4", "lru-dict==1.3.0", diff --git a/requirements.txt b/requirements.txt index 98ba315294b..c15e23553d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ ciso8601==2.3.1 fnv-hash-fast==1.0.2 hass-nabucasa==0.81.1 httpx==0.27.2 -home-assistant-bluetooth==1.12.2 +home-assistant-bluetooth==1.13.0 ifaddr==0.2.0 Jinja2==3.1.4 lru-dict==1.3.0 From ba4d081021d03fa4b6c10aabb6b197e89824d3ef Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Sat, 12 Oct 2024 20:22:03 +0200 Subject: [PATCH 75/89] Fix printer uptime fluctuations in IPP (#127725) * decrease uptime accuracy from seconds to minutes * adjust tests * calc uptime timestamp in coordinator * bump pyipp to 0.17.0 * revert changes, just use the new printer.booted_at property --------- Co-authored-by: Chris Talkington --- homeassistant/components/ipp/manifest.json | 2 +- homeassistant/components/ipp/sensor.py | 5 ++--- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/ipp/snapshots/test_diagnostics.ambr | 1 + tests/components/ipp/test_diagnostics.py | 2 ++ 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/ipp/manifest.json b/homeassistant/components/ipp/manifest.json index 2ba82b2cfec..baa41cf00bd 100644 --- a/homeassistant/components/ipp/manifest.json +++ b/homeassistant/components/ipp/manifest.json @@ -8,6 +8,6 @@ "iot_class": "local_polling", "loggers": ["deepmerge", "pyipp"], "quality_scale": "platinum", - "requirements": ["pyipp==0.16.0"], + "requirements": ["pyipp==0.17.0"], "zeroconf": ["_ipps._tcp.local.", "_ipp._tcp.local."] } diff --git a/homeassistant/components/ipp/sensor.py b/homeassistant/components/ipp/sensor.py index e872fc7977f..a2792c7749b 100644 --- a/homeassistant/components/ipp/sensor.py +++ b/homeassistant/components/ipp/sensor.py @@ -4,7 +4,7 @@ from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass -from datetime import datetime, timedelta +from datetime import datetime from typing import Any from pyipp import Marker, Printer @@ -19,7 +19,6 @@ from homeassistant.const import ATTR_LOCATION, PERCENTAGE, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType -from homeassistant.util.dt import utcnow from . import IPPConfigEntry from .const import ( @@ -80,7 +79,7 @@ PRINTER_SENSORS: tuple[IPPSensorEntityDescription, ...] = ( device_class=SensorDeviceClass.TIMESTAMP, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, - value_fn=lambda printer: (utcnow() - timedelta(seconds=printer.info.uptime)), + value_fn=lambda printer: printer.booted_at, ), ) diff --git a/requirements_all.txt b/requirements_all.txt index 4818ded19dc..ac0bd21ddf3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1960,7 +1960,7 @@ pyintesishome==1.8.0 pyipma==3.0.7 # homeassistant.components.ipp -pyipp==0.16.0 +pyipp==0.17.0 # homeassistant.components.iqvia pyiqvia==2022.04.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ed42a88ef62..1c0eef48dad 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1574,7 +1574,7 @@ pyinsteon==1.6.3 pyipma==3.0.7 # homeassistant.components.ipp -pyipp==0.16.0 +pyipp==0.17.0 # homeassistant.components.iqvia pyiqvia==2022.04.0 diff --git a/tests/components/ipp/snapshots/test_diagnostics.ambr b/tests/components/ipp/snapshots/test_diagnostics.ambr index 98d0055c982..bd2564c5a40 100644 --- a/tests/components/ipp/snapshots/test_diagnostics.ambr +++ b/tests/components/ipp/snapshots/test_diagnostics.ambr @@ -2,6 +2,7 @@ # name: test_diagnostics dict({ 'data': dict({ + 'booted_at': '2019-11-11T09:10:02+00:00', 'info': dict({ 'command_set': 'ESCPL2,BDC,D4,D4PX,ESCPR7,END4,GENEP,URF', 'location': None, diff --git a/tests/components/ipp/test_diagnostics.py b/tests/components/ipp/test_diagnostics.py index 08446601e69..d78f066d788 100644 --- a/tests/components/ipp/test_diagnostics.py +++ b/tests/components/ipp/test_diagnostics.py @@ -1,5 +1,6 @@ """Tests for the diagnostics data provided by the Internet Printing Protocol (IPP) integration.""" +import pytest from syrupy import SnapshotAssertion from homeassistant.core import HomeAssistant @@ -9,6 +10,7 @@ from tests.components.diagnostics import get_diagnostics_for_config_entry from tests.typing import ClientSessionGenerator +@pytest.mark.freeze_time("2019-11-11 09:10:32+00:00") async def test_diagnostics( hass: HomeAssistant, hass_client: ClientSessionGenerator, From 14127b910f40946a9d5b2926a2f4133d1a37fc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=B6rsken?= Date: Fri, 11 Oct 2024 20:40:03 +0200 Subject: [PATCH 76/89] Improve discovery of WMS WebControl pro by updating IP address (#128007) --- .../components/wmspro/config_flow.py | 15 +++- tests/components/wmspro/test_config_flow.py | 90 +++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/wmspro/config_flow.py b/homeassistant/components/wmspro/config_flow.py index 19b9ab28e6a..c28cf5efce3 100644 --- a/homeassistant/components/wmspro/config_flow.py +++ b/homeassistant/components/wmspro/config_flow.py @@ -2,6 +2,7 @@ from __future__ import annotations +import ipaddress import logging from typing import Any @@ -38,7 +39,19 @@ class WebControlProConfigFlow(ConfigFlow, domain=DOMAIN): """Handle the DHCP discovery step.""" unique_id = format_mac(discovery_info.macaddress) await self.async_set_unique_id(unique_id) - self._abort_if_unique_id_configured() + + entry = self.hass.config_entries.async_entry_for_domain_unique_id( + DOMAIN, unique_id + ) + if entry: + try: # Check if current host is a valid IP address + ipaddress.ip_address(entry.data[CONF_HOST]) + except ValueError: # Do not touch name-based host + return self.async_abort(reason="already_configured") + else: # Update existing host with new IP address + self._abort_if_unique_id_configured( + updates={CONF_HOST: discovery_info.ip} + ) for entry in self.hass.config_entries.async_entries(DOMAIN): if not entry.unique_id and entry.data[CONF_HOST] in ( diff --git a/tests/components/wmspro/test_config_flow.py b/tests/components/wmspro/test_config_flow.py index 6a254a93836..c25641a8979 100644 --- a/tests/components/wmspro/test_config_flow.py +++ b/tests/components/wmspro/test_config_flow.py @@ -112,6 +112,96 @@ async def test_config_flow_from_dhcp_add_mac( assert hass.config_entries.async_entries(DOMAIN)[0].unique_id == "00:11:22:33:44:55" +async def test_config_flow_from_dhcp_ip_update( + hass: HomeAssistant, + mock_setup_entry: AsyncMock, +) -> None: + """Test we can use DHCP discovery to update IP in a config entry.""" + info = DhcpServiceInfo( + ip="1.2.3.4", hostname="webcontrol", macaddress="00:11:22:33:44:55" + ) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_DHCP}, data=info + ) + assert result["type"] is FlowResultType.FORM + assert result["errors"] == {} + + with patch( + "wmspro.webcontrol.WebControlPro.ping", + return_value=True, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "1.2.3.4", + }, + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == "1.2.3.4" + assert result["data"] == { + CONF_HOST: "1.2.3.4", + } + assert len(mock_setup_entry.mock_calls) == 1 + assert hass.config_entries.async_entries(DOMAIN)[0].unique_id == "00:11:22:33:44:55" + + info = DhcpServiceInfo( + ip="5.6.7.8", hostname="webcontrol", macaddress="00:11:22:33:44:55" + ) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_DHCP}, data=info + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert hass.config_entries.async_entries(DOMAIN)[0].unique_id == "00:11:22:33:44:55" + assert hass.config_entries.async_entries(DOMAIN)[0].data[CONF_HOST] == "5.6.7.8" + + +async def test_config_flow_from_dhcp_no_update( + hass: HomeAssistant, + mock_setup_entry: AsyncMock, +) -> None: + """Test we do not use DHCP discovery to overwrite hostname with IP in config entry.""" + info = DhcpServiceInfo( + ip="1.2.3.4", hostname="webcontrol", macaddress="00:11:22:33:44:55" + ) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_DHCP}, data=info + ) + assert result["type"] is FlowResultType.FORM + assert result["errors"] == {} + + with patch( + "wmspro.webcontrol.WebControlPro.ping", + return_value=True, + ): + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + { + CONF_HOST: "webcontrol", + }, + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["title"] == "webcontrol" + assert result["data"] == { + CONF_HOST: "webcontrol", + } + assert len(mock_setup_entry.mock_calls) == 1 + assert hass.config_entries.async_entries(DOMAIN)[0].unique_id == "00:11:22:33:44:55" + + info = DhcpServiceInfo( + ip="5.6.7.8", hostname="webcontrol", macaddress="00:11:22:33:44:55" + ) + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_DHCP}, data=info + ) + assert result["type"] is FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert hass.config_entries.async_entries(DOMAIN)[0].unique_id == "00:11:22:33:44:55" + assert hass.config_entries.async_entries(DOMAIN)[0].data[CONF_HOST] == "webcontrol" + + async def test_config_flow_ping_failed( hass: HomeAssistant, mock_setup_entry: AsyncMock ) -> None: From 0a26e68d0cd23cf4d5fa1ad1cb0cf22251eb28d5 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Thu, 17 Oct 2024 07:17:20 -0400 Subject: [PATCH 77/89] Use the same ZHA database path during startup and when loading device triggers (#128130) Use the same zigpy database path source as in the radio manager --- homeassistant/components/zha/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/zha/helpers.py b/homeassistant/components/zha/helpers.py index b91565835a7..e8d53ac11ad 100644 --- a/homeassistant/components/zha/helpers.py +++ b/homeassistant/components/zha/helpers.py @@ -1198,7 +1198,7 @@ def create_zha_config(hass: HomeAssistant, ha_zha_data: HAZHAData) -> ZHAData: # deep copy the yaml config to avoid modifying the original and to safely # pass it to the ZHA library app_config = copy.deepcopy(ha_zha_data.yaml_config.get(CONF_ZIGPY, {})) - database = app_config.get( + database = ha_zha_data.yaml_config.get( CONF_DATABASE, hass.config.path(DEFAULT_DATABASE_NAME), ) From 76340035dbe0b67e3a728785a2c9ba5e3bc446a3 Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Sun, 13 Oct 2024 12:41:51 -0500 Subject: [PATCH 78/89] Fix playing media via roku (#128133) * re-support playing media via roku * fixes * test fixes * Update test_media_player.py * always send media type * add description to options flow --- homeassistant/components/roku/__init__.py | 16 ++++++- homeassistant/components/roku/config_flow.py | 42 ++++++++++++++++- homeassistant/components/roku/const.py | 6 +++ homeassistant/components/roku/coordinator.py | 7 +-- homeassistant/components/roku/media_player.py | 14 ++++-- homeassistant/components/roku/strings.json | 12 +++++ tests/components/roku/test_config_flow.py | 24 +++++++++- tests/components/roku/test_media_player.py | 47 ++++++++++++------- 8 files changed, 138 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/roku/__init__.py b/homeassistant/components/roku/__init__.py index 7515f375054..b318a91e4c7 100644 --- a/homeassistant/components/roku/__init__.py +++ b/homeassistant/components/roku/__init__.py @@ -6,7 +6,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, Platform from homeassistant.core import HomeAssistant -from .const import DOMAIN +from .const import CONF_PLAY_MEDIA_APP_ID, DEFAULT_PLAY_MEDIA_APP_ID, DOMAIN from .coordinator import RokuDataUpdateCoordinator PLATFORMS = [ @@ -24,7 +24,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: device_id = entry.entry_id coordinator = RokuDataUpdateCoordinator( - hass, host=entry.data[CONF_HOST], device_id=device_id + hass, + host=entry.data[CONF_HOST], + device_id=device_id, + play_media_app_id=entry.options.get( + CONF_PLAY_MEDIA_APP_ID, DEFAULT_PLAY_MEDIA_APP_ID + ), ) await coordinator.async_config_entry_first_refresh() @@ -32,6 +37,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + entry.async_on_unload(entry.add_update_listener(async_reload_entry)) + return True @@ -40,3 +47,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): hass.data[DOMAIN].pop(entry.entry_id) return unload_ok + + +async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: + """Reload the config entry when it changed.""" + await hass.config_entries.async_reload(entry.entry_id) diff --git a/homeassistant/components/roku/config_flow.py b/homeassistant/components/roku/config_flow.py index 7757cc53e1c..3ece9aff3f2 100644 --- a/homeassistant/components/roku/config_flow.py +++ b/homeassistant/components/roku/config_flow.py @@ -10,12 +10,17 @@ from rokuecp import Roku, RokuError import voluptuous as vol from homeassistant.components import ssdp, zeroconf -from homeassistant.config_entries import ConfigFlow, ConfigFlowResult +from homeassistant.config_entries import ( + ConfigEntry, + ConfigFlow, + ConfigFlowResult, + OptionsFlowWithConfigEntry, +) from homeassistant.const import CONF_HOST, CONF_NAME from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.aiohttp_client import async_get_clientsession -from .const import DOMAIN +from .const import CONF_PLAY_MEDIA_APP_ID, DEFAULT_PLAY_MEDIA_APP_ID, DOMAIN DATA_SCHEMA = vol.Schema({vol.Required(CONF_HOST): str}) @@ -155,3 +160,36 @@ class RokuConfigFlow(ConfigFlow, domain=DOMAIN): title=self.discovery_info[CONF_NAME], data=self.discovery_info, ) + + @staticmethod + @callback + def async_get_options_flow( + config_entry: ConfigEntry, + ) -> OptionsFlowWithConfigEntry: + """Create the options flow.""" + return RokuOptionsFlowHandler(config_entry) + + +class RokuOptionsFlowHandler(OptionsFlowWithConfigEntry): + """Handle Roku options.""" + + async def async_step_init( + self, user_input: dict[str, Any] | None = None + ) -> ConfigFlowResult: + """Manage Roku options.""" + if user_input is not None: + return self.async_create_entry(title="", data=user_input) + + return self.async_show_form( + step_id="init", + data_schema=vol.Schema( + { + vol.Optional( + CONF_PLAY_MEDIA_APP_ID, + default=self.options.get( + CONF_PLAY_MEDIA_APP_ID, DEFAULT_PLAY_MEDIA_APP_ID + ), + ): str, + } + ), + ) diff --git a/homeassistant/components/roku/const.py b/homeassistant/components/roku/const.py index ab633a4044c..f0c7d4e2537 100644 --- a/homeassistant/components/roku/const.py +++ b/homeassistant/components/roku/const.py @@ -15,3 +15,9 @@ DEFAULT_PORT = 8060 # Services SERVICE_SEARCH = "search" + +# Config +CONF_PLAY_MEDIA_APP_ID = "play_media_app_id" + +# Defaults +DEFAULT_PLAY_MEDIA_APP_ID = "15985" diff --git a/homeassistant/components/roku/coordinator.py b/homeassistant/components/roku/coordinator.py index 303d0e91a36..7900669d02f 100644 --- a/homeassistant/components/roku/coordinator.py +++ b/homeassistant/components/roku/coordinator.py @@ -29,15 +29,12 @@ class RokuDataUpdateCoordinator(DataUpdateCoordinator[Device]): roku: Roku def __init__( - self, - hass: HomeAssistant, - *, - host: str, - device_id: str, + self, hass: HomeAssistant, *, host: str, device_id: str, play_media_app_id: str ) -> None: """Initialize global Roku data updater.""" self.device_id = device_id self.roku = Roku(host=host, session=async_get_clientsession(hass)) + self.play_media_app_id = play_media_app_id self.full_update_interval = timedelta(minutes=15) self.last_full_update = None diff --git a/homeassistant/components/roku/media_player.py b/homeassistant/components/roku/media_player.py index 5b15253068e..35f01553cdd 100644 --- a/homeassistant/components/roku/media_player.py +++ b/homeassistant/components/roku/media_player.py @@ -445,17 +445,25 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity): if attr in extra } - params = {"t": "a", **params} + params = {"u": media_id, "t": "a", **params} - await self.coordinator.roku.play_on_roku(media_id, params) + await self.coordinator.roku.launch( + self.coordinator.play_media_app_id, + params, + ) elif media_type in {MediaType.URL, MediaType.VIDEO}: params = { param: extra[attr] for (attr, param) in ATTRS_TO_PLAY_ON_ROKU_PARAMS.items() if attr in extra } + params["u"] = media_id + params["t"] = "v" - await self.coordinator.roku.play_on_roku(media_id, params) + await self.coordinator.roku.launch( + self.coordinator.play_media_app_id, + params, + ) else: _LOGGER.error("Media type %s is not supported", original_media_type) return diff --git a/homeassistant/components/roku/strings.json b/homeassistant/components/roku/strings.json index 9eef366163e..9d657be6d61 100644 --- a/homeassistant/components/roku/strings.json +++ b/homeassistant/components/roku/strings.json @@ -24,6 +24,18 @@ "unknown": "[%key:common::config_flow::error::unknown%]" } }, + "options": { + "step": { + "init": { + "data": { + "play_media_app_id": "Play Media Roku Application ID" + }, + "data_description": { + "play_media_app_id": "The application ID to use when launching media playback. Must support the PlayOnRoku API." + } + } + } + }, "entity": { "binary_sensor": { "headphones_connected": { diff --git a/tests/components/roku/test_config_flow.py b/tests/components/roku/test_config_flow.py index 3cf5627f342..7144c77cad9 100644 --- a/tests/components/roku/test_config_flow.py +++ b/tests/components/roku/test_config_flow.py @@ -6,7 +6,7 @@ from unittest.mock import MagicMock import pytest from rokuecp import RokuConnectionError -from homeassistant.components.roku.const import DOMAIN +from homeassistant.components.roku.const import CONF_PLAY_MEDIA_APP_ID, DOMAIN from homeassistant.config_entries import SOURCE_HOMEKIT, SOURCE_SSDP, SOURCE_USER from homeassistant.const import CONF_HOST, CONF_NAME, CONF_SOURCE from homeassistant.core import HomeAssistant @@ -254,3 +254,25 @@ async def test_ssdp_discovery( assert result["data"] assert result["data"][CONF_HOST] == HOST assert result["data"][CONF_NAME] == UPNP_FRIENDLY_NAME + + +async def test_options_flow( + hass: HomeAssistant, mock_config_entry: MockConfigEntry +) -> None: + """Test options config flow.""" + mock_config_entry.add_to_hass(hass) + + result = await hass.config_entries.options.async_init(mock_config_entry.entry_id) + + assert result.get("type") is FlowResultType.FORM + assert result.get("step_id") == "init" + + result2 = await hass.config_entries.options.async_configure( + result["flow_id"], + user_input={CONF_PLAY_MEDIA_APP_ID: "782875"}, + ) + + assert result2.get("type") is FlowResultType.CREATE_ENTRY + assert result2.get("data") == { + CONF_PLAY_MEDIA_APP_ID: "782875", + } diff --git a/tests/components/roku/test_media_player.py b/tests/components/roku/test_media_player.py index 9aff8f581d7..03b1999ae83 100644 --- a/tests/components/roku/test_media_player.py +++ b/tests/components/roku/test_media_player.py @@ -32,6 +32,7 @@ from homeassistant.components.roku.const import ( ATTR_FORMAT, ATTR_KEYWORD, ATTR_MEDIA_TYPE, + DEFAULT_PLAY_MEDIA_APP_ID, DOMAIN, SERVICE_SEARCH, ) @@ -495,7 +496,7 @@ async def test_services_play_media( blocking=True, ) - assert mock_roku.play_on_roku.call_count == 0 + assert mock_roku.launch.call_count == 0 await hass.services.async_call( MP_DOMAIN, @@ -509,7 +510,7 @@ async def test_services_play_media( blocking=True, ) - assert mock_roku.play_on_roku.call_count == 0 + assert mock_roku.launch.call_count == 0 @pytest.mark.parametrize( @@ -546,9 +547,10 @@ async def test_services_play_media_audio( }, blocking=True, ) - mock_roku.play_on_roku.assert_called_once_with( - content_id, + mock_roku.launch.assert_called_once_with( + DEFAULT_PLAY_MEDIA_APP_ID, { + "u": content_id, "t": "a", "songName": resolved_name, "songFormat": resolved_format, @@ -591,9 +593,11 @@ async def test_services_play_media_video( }, blocking=True, ) - mock_roku.play_on_roku.assert_called_once_with( - content_id, + mock_roku.launch.assert_called_once_with( + DEFAULT_PLAY_MEDIA_APP_ID, { + "u": content_id, + "t": "v", "videoName": resolved_name, "videoFormat": resolved_format, }, @@ -617,10 +621,12 @@ async def test_services_camera_play_stream( blocking=True, ) - assert mock_roku.play_on_roku.call_count == 1 - mock_roku.play_on_roku.assert_called_with( - "https://awesome.tld/api/hls/api_token/master_playlist.m3u8", + assert mock_roku.launch.call_count == 1 + mock_roku.launch.assert_called_with( + DEFAULT_PLAY_MEDIA_APP_ID, { + "u": "https://awesome.tld/api/hls/api_token/master_playlist.m3u8", + "t": "v", "videoName": "Camera Stream", "videoFormat": "hls", }, @@ -653,14 +659,21 @@ async def test_services_play_media_local_source( blocking=True, ) - assert mock_roku.play_on_roku.call_count == 1 - assert mock_roku.play_on_roku.call_args - call_args = mock_roku.play_on_roku.call_args.args - assert "/local/Epic%20Sax%20Guy%2010%20Hours.mp4?authSig=" in call_args[0] - assert call_args[1] == { - "videoFormat": "mp4", - "videoName": "media-source://media_source/local/Epic Sax Guy 10 Hours.mp4", - } + assert mock_roku.launch.call_count == 1 + assert mock_roku.launch.call_args + call_args = mock_roku.launch.call_args.args + assert call_args[0] == DEFAULT_PLAY_MEDIA_APP_ID + assert "u" in call_args[1] + assert "/local/Epic%20Sax%20Guy%2010%20Hours.mp4?authSig=" in call_args[1]["u"] + assert "t" in call_args[1] + assert call_args[1]["t"] == "v" + assert "videoFormat" in call_args[1] + assert call_args[1]["videoFormat"] == "mp4" + assert "videoName" in call_args[1] + assert ( + call_args[1]["videoName"] + == "media-source://media_source/local/Epic Sax Guy 10 Hours.mp4" + ) @pytest.mark.parametrize("mock_device", ["roku/rokutv-7820x.json"], indirect=True) From 5a8fa6cf38fa3e1c068d2e17440d58c94b608a1b Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 11 Oct 2024 19:54:10 +0200 Subject: [PATCH 79/89] Bump yt-dlp to 2024.10.07 (#128182) --- homeassistant/components/media_extractor/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_extractor/manifest.json b/homeassistant/components/media_extractor/manifest.json index 635ab5f6d40..fa7657244d6 100644 --- a/homeassistant/components/media_extractor/manifest.json +++ b/homeassistant/components/media_extractor/manifest.json @@ -8,6 +8,6 @@ "iot_class": "calculated", "loggers": ["yt_dlp"], "quality_scale": "internal", - "requirements": ["yt-dlp==2024.09.27"], + "requirements": ["yt-dlp==2024.10.07"], "single_config_entry": true } diff --git a/requirements_all.txt b/requirements_all.txt index ac0bd21ddf3..df4932145d9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -3032,7 +3032,7 @@ youless-api==2.1.2 youtubeaio==1.1.5 # homeassistant.components.media_extractor -yt-dlp==2024.09.27 +yt-dlp==2024.10.07 # homeassistant.components.zamg zamg==0.3.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1c0eef48dad..1b3bf01faaa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2415,7 +2415,7 @@ youless-api==2.1.2 youtubeaio==1.1.5 # homeassistant.components.media_extractor -yt-dlp==2024.09.27 +yt-dlp==2024.10.07 # homeassistant.components.zamg zamg==0.3.6 From d66d87d271437ddab452f5e22532f174959d3986 Mon Sep 17 00:00:00 2001 From: Adam Petrovic Date: Sun, 13 Oct 2024 22:20:16 +1100 Subject: [PATCH 80/89] Fix daikin entities not refreshing quickly (#128230) * Fix daikin entities not refreshing quickly * Update homeassistant/components/daikin/switch.py --------- Co-authored-by: Joost Lekkerkerker --- homeassistant/components/daikin/climate.py | 4 ++++ homeassistant/components/daikin/switch.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/homeassistant/components/daikin/climate.py b/homeassistant/components/daikin/climate.py index f1fc0473115..39e92ab1921 100644 --- a/homeassistant/components/daikin/climate.py +++ b/homeassistant/components/daikin/climate.py @@ -159,6 +159,7 @@ class DaikinClimate(DaikinEntity, ClimateEntity): if values: await self.device.set(values) + await self.coordinator.async_refresh() @property def unique_id(self) -> str: @@ -261,6 +262,7 @@ class DaikinClimate(DaikinEntity, ClimateEntity): await self.device.set_advanced_mode( HA_PRESET_TO_DAIKIN[PRESET_ECO], ATTR_STATE_OFF ) + await self.coordinator.async_refresh() @property def preset_modes(self) -> list[str]: @@ -275,9 +277,11 @@ class DaikinClimate(DaikinEntity, ClimateEntity): async def async_turn_on(self) -> None: """Turn device on.""" await self.device.set({}) + await self.coordinator.async_refresh() async def async_turn_off(self) -> None: """Turn device off.""" await self.device.set( {HA_ATTR_TO_DAIKIN[ATTR_HVAC_MODE]: HA_STATE_TO_DAIKIN[HVACMode.OFF]} ) + await self.coordinator.async_refresh() diff --git a/homeassistant/components/daikin/switch.py b/homeassistant/components/daikin/switch.py index 23517d085d2..669048ac45e 100644 --- a/homeassistant/components/daikin/switch.py +++ b/homeassistant/components/daikin/switch.py @@ -63,10 +63,12 @@ class DaikinZoneSwitch(DaikinEntity, SwitchEntity): async def async_turn_on(self, **kwargs: Any) -> None: """Turn the zone on.""" await self.device.set_zone(self._zone_id, "zone_onoff", "1") + await self.coordinator.async_refresh() async def async_turn_off(self, **kwargs: Any) -> None: """Turn the zone off.""" await self.device.set_zone(self._zone_id, "zone_onoff", "0") + await self.coordinator.async_refresh() class DaikinStreamerSwitch(DaikinEntity, SwitchEntity): @@ -88,10 +90,12 @@ class DaikinStreamerSwitch(DaikinEntity, SwitchEntity): async def async_turn_on(self, **kwargs: Any) -> None: """Turn the zone on.""" await self.device.set_streamer("on") + await self.coordinator.async_refresh() async def async_turn_off(self, **kwargs: Any) -> None: """Turn the zone off.""" await self.device.set_streamer("off") + await self.coordinator.async_refresh() class DaikinToggleSwitch(DaikinEntity, SwitchEntity): @@ -112,7 +116,9 @@ class DaikinToggleSwitch(DaikinEntity, SwitchEntity): async def async_turn_on(self, **kwargs: Any) -> None: """Turn the zone on.""" await self.device.set({}) + await self.coordinator.async_refresh() async def async_turn_off(self, **kwargs: Any) -> None: """Turn the zone off.""" await self.device.set({DAIKIN_ATTR_MODE: "off"}) + await self.coordinator.async_refresh() From f9cbf1b30ce1f1b6480723ebb81dac8e2c01db09 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:22:12 +0200 Subject: [PATCH 81/89] Keep the provided name when creating a tag (#128240) * Keep the name * Add patch * Update homeassistant/components/tag/__init__.py Co-authored-by: G Johansson --------- Co-authored-by: G Johansson --- homeassistant/components/tag/__init__.py | 4 +++- tests/components/tag/test_init.py | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/tag/__init__.py b/homeassistant/components/tag/__init__.py index 0462c5bec34..95efae3d386 100644 --- a/homeassistant/components/tag/__init__.py +++ b/homeassistant/components/tag/__init__.py @@ -84,7 +84,9 @@ def _create_entry( original_name=f"{DEFAULT_NAME} {tag_id}", suggested_object_id=slugify(name) if name else tag_id, ) - return entity_registry.async_update_entity(entry.entity_id, name=name) + if name: + return entity_registry.async_update_entity(entry.entity_id, name=name) + return entry class TagStore(Store[collection.SerializedStorageCollection]): diff --git a/tests/components/tag/test_init.py b/tests/components/tag/test_init.py index 6f309391d2b..5c1e80c2d8b 100644 --- a/tests/components/tag/test_init.py +++ b/tests/components/tag/test_init.py @@ -294,6 +294,10 @@ async def test_entity_created_and_removed( assert item["id"] == "1234567890" assert item["name"] == "Kitchen tag" + await hass.async_block_till_done() + er_entity = entity_registry.async_get("tag.kitchen_tag") + assert er_entity.name == "Kitchen tag" + entity = hass.states.get("tag.kitchen_tag") assert entity assert entity.state == STATE_UNKNOWN From 7d2536c5036c41715b11816ca2ff5ea1b7de5ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Fri, 11 Oct 2024 12:39:39 +0200 Subject: [PATCH 82/89] Update aioairzone to v0.9.4 (#127792) --- homeassistant/components/airzone/climate.py | 4 +- .../components/airzone/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- .../airzone/snapshots/test_diagnostics.ambr | 100 +++++++++++++++++- tests/components/airzone/test_climate.py | 17 +++ tests/components/airzone/util.py | 31 ++++++ 7 files changed, 152 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/airzone/climate.py b/homeassistant/components/airzone/climate.py index 5e5e1c126de..559513d3439 100644 --- a/homeassistant/components/airzone/climate.py +++ b/homeassistant/components/airzone/climate.py @@ -85,6 +85,7 @@ HVAC_MODE_LIB_TO_HASS: Final[dict[OperationMode, HVACMode]] = { OperationMode.HEATING: HVACMode.HEAT, OperationMode.FAN: HVACMode.FAN_ONLY, OperationMode.DRY: HVACMode.DRY, + OperationMode.AUX_HEATING: HVACMode.HEAT, OperationMode.AUTO: HVACMode.HEAT_COOL, } HVAC_MODE_HASS_TO_LIB: Final[dict[HVACMode, OperationMode]] = { @@ -157,9 +158,10 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity): self._attr_temperature_unit = TEMP_UNIT_LIB_TO_HASS[ self.get_airzone_value(AZD_TEMP_UNIT) ] - self._attr_hvac_modes = [ + _attr_hvac_modes = [ HVAC_MODE_LIB_TO_HASS[mode] for mode in self.get_airzone_value(AZD_MODES) ] + self._attr_hvac_modes = list(dict.fromkeys(_attr_hvac_modes)) if ( self.get_airzone_value(AZD_SPEED) is not None and self.get_airzone_value(AZD_SPEEDS) is not None diff --git a/homeassistant/components/airzone/manifest.json b/homeassistant/components/airzone/manifest.json index c40f4138b0a..87d2c5e68b0 100644 --- a/homeassistant/components/airzone/manifest.json +++ b/homeassistant/components/airzone/manifest.json @@ -11,5 +11,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone", "iot_class": "local_polling", "loggers": ["aioairzone"], - "requirements": ["aioairzone==0.9.3"] + "requirements": ["aioairzone==0.9.4"] } diff --git a/requirements_all.txt b/requirements_all.txt index df4932145d9..8271ce14338 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -179,7 +179,7 @@ aioairq==0.3.2 aioairzone-cloud==0.6.6 # homeassistant.components.airzone -aioairzone==0.9.3 +aioairzone==0.9.4 # homeassistant.components.ambient_network # homeassistant.components.ambient_station diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1b3bf01faaa..ac8393e89eb 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -167,7 +167,7 @@ aioairq==0.3.2 aioairzone-cloud==0.6.6 # homeassistant.components.airzone -aioairzone==0.9.3 +aioairzone==0.9.4 # homeassistant.components.ambient_network # homeassistant.components.ambient_station diff --git a/tests/components/airzone/snapshots/test_diagnostics.ambr b/tests/components/airzone/snapshots/test_diagnostics.ambr index 693550a3e1c..fb4f6530b1e 100644 --- a/tests/components/airzone/snapshots/test_diagnostics.ambr +++ b/tests/components/airzone/snapshots/test_diagnostics.ambr @@ -220,6 +220,45 @@ }), ]), }), + dict({ + 'data': list([ + dict({ + 'air_demand': 0, + 'coldStage': 0, + 'coldStages': 0, + 'coolmaxtemp': 30, + 'coolmintemp': 15, + 'coolsetpoint': 20, + 'errors': list([ + ]), + 'floor_demand': 0, + 'heatStage': 0, + 'heatStages': 0, + 'heatmaxtemp': 30, + 'heatmintemp': 15, + 'heatsetpoint': 20, + 'humidity': 0, + 'maxTemp': 30, + 'minTemp': 15, + 'mode': 6, + 'modes': list([ + 1, + 2, + 3, + 4, + 5, + 6, + ]), + 'name': 'Aux Heat', + 'on': 1, + 'roomTemp': 22, + 'setpoint': 20, + 'systemID': 4, + 'units': 0, + 'zoneID': 1, + }), + ]), + }), ]), }), 'version': dict({ @@ -269,8 +308,8 @@ 'temp-set': 45, 'temp-unit': 0, }), - 'num-systems': 3, - 'num-zones': 7, + 'num-systems': 4, + 'num-zones': 8, 'systems': dict({ '1': dict({ 'available': True, @@ -320,6 +359,23 @@ ]), 'problems': False, }), + '4': dict({ + 'available': True, + 'full-name': 'Airzone [4] System', + 'id': 4, + 'master-system-zone': '4:1', + 'master-zone': 1, + 'mode': 6, + 'modes': list([ + 1, + 2, + 3, + 4, + 5, + 6, + ]), + 'problems': False, + }), }), 'version': '1.62', 'webserver': dict({ @@ -683,6 +739,46 @@ 'temp-step': 1.0, 'temp-unit': 1, }), + '4:1': dict({ + 'absolute-temp-max': 30.0, + 'absolute-temp-min': 15.0, + 'action': 5, + 'air-demand': False, + 'available': True, + 'cold-stage': 0, + 'cool-temp-max': 30.0, + 'cool-temp-min': 15.0, + 'cool-temp-set': 20.0, + 'demand': False, + 'double-set-point': False, + 'floor-demand': False, + 'full-name': 'Airzone [4:1] Aux Heat', + 'heat-stage': 0, + 'heat-temp-max': 30.0, + 'heat-temp-min': 15.0, + 'heat-temp-set': 20.0, + 'id': 1, + 'master': True, + 'mode': 6, + 'modes': list([ + 1, + 2, + 3, + 4, + 5, + 6, + ]), + 'name': 'Aux Heat', + 'on': True, + 'problems': False, + 'system': 4, + 'temp': 22.0, + 'temp-max': 30.0, + 'temp-min': 15.0, + 'temp-set': 20.0, + 'temp-step': 0.5, + 'temp-unit': 0, + }), }), }), }) diff --git a/tests/components/airzone/test_climate.py b/tests/components/airzone/test_climate.py index 0f23c151e0e..12a73a6a268 100644 --- a/tests/components/airzone/test_climate.py +++ b/tests/components/airzone/test_climate.py @@ -225,6 +225,23 @@ async def test_airzone_create_climates(hass: HomeAssistant) -> None: assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) == 25.0 assert state.attributes.get(ATTR_TARGET_TEMP_LOW) == 22.8 + state = hass.states.get("climate.aux_heat") + assert state.state == HVACMode.HEAT + assert state.attributes.get(ATTR_CURRENT_HUMIDITY) is None + assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) == 22 + assert state.attributes.get(ATTR_HVAC_ACTION) == HVACAction.IDLE + assert state.attributes.get(ATTR_HVAC_MODES) == [ + HVACMode.OFF, + HVACMode.COOL, + HVACMode.HEAT, + HVACMode.FAN_ONLY, + HVACMode.DRY, + ] + assert state.attributes.get(ATTR_MAX_TEMP) == 30 + assert state.attributes.get(ATTR_MIN_TEMP) == 15 + assert state.attributes.get(ATTR_TARGET_TEMP_STEP) == API_TEMPERATURE_STEP + assert state.attributes.get(ATTR_TEMPERATURE) == 20.0 + HVAC_MOCK_CHANGED = copy.deepcopy(HVAC_MOCK) HVAC_MOCK_CHANGED[API_SYSTEMS][0][API_DATA][0][API_MAX_TEMP] = 25 HVAC_MOCK_CHANGED[API_SYSTEMS][0][API_DATA][0][API_MIN_TEMP] = 10 diff --git a/tests/components/airzone/util.py b/tests/components/airzone/util.py index 2cdb7a9c6f9..278663b7a97 100644 --- a/tests/components/airzone/util.py +++ b/tests/components/airzone/util.py @@ -272,6 +272,37 @@ HVAC_MOCK = { }, ] }, + { + API_DATA: [ + { + API_SYSTEM_ID: 4, + API_ZONE_ID: 1, + API_NAME: "Aux Heat", + API_ON: 1, + API_COOL_SET_POINT: 20, + API_COOL_MAX_TEMP: 30, + API_COOL_MIN_TEMP: 15, + API_HEAT_SET_POINT: 20, + API_HEAT_MAX_TEMP: 30, + API_HEAT_MIN_TEMP: 15, + API_MAX_TEMP: 30, + API_MIN_TEMP: 15, + API_SET_POINT: 20, + API_ROOM_TEMP: 22, + API_MODES: [1, 2, 3, 4, 5, 6], + API_MODE: 6, + API_COLD_STAGES: 0, + API_COLD_STAGE: 0, + API_HEAT_STAGES: 0, + API_HEAT_STAGE: 0, + API_HUMIDITY: 0, + API_UNITS: 0, + API_ERRORS: [], + API_AIR_DEMAND: 0, + API_FLOOR_DEMAND: 0, + }, + ] + }, ] } From 0e8393766f55504f5f6b90e71de4fb97ca830f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Sun, 13 Oct 2024 12:45:53 +0200 Subject: [PATCH 83/89] Update aioairzone to v0.9.5 (#128265) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Fernández Rojas --- homeassistant/components/airzone/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/airzone/manifest.json b/homeassistant/components/airzone/manifest.json index 87d2c5e68b0..10fb20bb2ce 100644 --- a/homeassistant/components/airzone/manifest.json +++ b/homeassistant/components/airzone/manifest.json @@ -11,5 +11,5 @@ "documentation": "https://www.home-assistant.io/integrations/airzone", "iot_class": "local_polling", "loggers": ["aioairzone"], - "requirements": ["aioairzone==0.9.4"] + "requirements": ["aioairzone==0.9.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8271ce14338..10b20f1faa6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -179,7 +179,7 @@ aioairq==0.3.2 aioairzone-cloud==0.6.6 # homeassistant.components.airzone -aioairzone==0.9.4 +aioairzone==0.9.5 # homeassistant.components.ambient_network # homeassistant.components.ambient_station diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ac8393e89eb..4826c00cddf 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -167,7 +167,7 @@ aioairq==0.3.2 aioairzone-cloud==0.6.6 # homeassistant.components.airzone -aioairzone==0.9.4 +aioairzone==0.9.5 # homeassistant.components.ambient_network # homeassistant.components.ambient_station From ea7473ed67675fcfc4475305fe7b764ca5872b22 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 13 Oct 2024 03:47:27 -0700 Subject: [PATCH 84/89] Bump gcal_sync to 6.1.6 (#128270) --- homeassistant/components/google/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/google/manifest.json b/homeassistant/components/google/manifest.json index 288ccbd6899..0245333d713 100644 --- a/homeassistant/components/google/manifest.json +++ b/homeassistant/components/google/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/calendar.google", "iot_class": "cloud_polling", "loggers": ["googleapiclient"], - "requirements": ["gcal-sync==6.1.5", "oauth2client==4.1.3", "ical==8.2.0"] + "requirements": ["gcal-sync==6.1.6", "oauth2client==4.1.3", "ical==8.2.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 10b20f1faa6..3157ced38f1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -945,7 +945,7 @@ gardena-bluetooth==1.4.3 gassist-text==0.0.11 # homeassistant.components.google -gcal-sync==6.1.5 +gcal-sync==6.1.6 # homeassistant.components.geniushub geniushub-client==0.7.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4826c00cddf..54f5adddb09 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -798,7 +798,7 @@ gardena-bluetooth==1.4.3 gassist-text==0.0.11 # homeassistant.components.google -gcal-sync==6.1.5 +gcal-sync==6.1.6 # homeassistant.components.geniushub geniushub-client==0.7.1 From 146768ff8a37ffe7f0f6e1635899ac751cef0ea5 Mon Sep 17 00:00:00 2001 From: dontinelli <73341522+dontinelli@users.noreply.github.com> Date: Sun, 13 Oct 2024 16:04:58 +0200 Subject: [PATCH 85/89] Bump solarlog_cli to 0.3.2 (#128293) --- homeassistant/components/solarlog/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/solarlog/manifest.json b/homeassistant/components/solarlog/manifest.json index 274c97c76b5..9f80b749d08 100644 --- a/homeassistant/components/solarlog/manifest.json +++ b/homeassistant/components/solarlog/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/solarlog", "iot_class": "local_polling", "loggers": ["solarlog_cli"], - "requirements": ["solarlog_cli==0.3.1"] + "requirements": ["solarlog_cli==0.3.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 3157ced38f1..239c3c52f09 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2676,7 +2676,7 @@ soco==0.30.4 solaredge-local==0.2.3 # homeassistant.components.solarlog -solarlog_cli==0.3.1 +solarlog_cli==0.3.2 # homeassistant.components.solax solax==3.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 54f5adddb09..1ee07086b28 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2122,7 +2122,7 @@ snapcast==2.3.6 soco==0.30.4 # homeassistant.components.solarlog -solarlog_cli==0.3.1 +solarlog_cli==0.3.2 # homeassistant.components.solax solax==3.1.1 From b018d4a97d42f06c2725919f62dce4bed8f10425 Mon Sep 17 00:00:00 2001 From: Louis Christ Date: Wed, 16 Oct 2024 18:59:03 +0200 Subject: [PATCH 86/89] Bump pyblu to 1.0.4 (#128482) --- homeassistant/components/bluesound/manifest.json | 2 +- homeassistant/components/bluesound/media_player.py | 2 ++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bluesound/manifest.json b/homeassistant/components/bluesound/manifest.json index 4d92a5f7fc0..462112a8b78 100644 --- a/homeassistant/components/bluesound/manifest.json +++ b/homeassistant/components/bluesound/manifest.json @@ -6,7 +6,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/bluesound", "iot_class": "local_polling", - "requirements": ["pyblu==1.0.3"], + "requirements": ["pyblu==1.0.4"], "zeroconf": [ { "type": "_musc._tcp.local." diff --git a/homeassistant/components/bluesound/media_player.py b/homeassistant/components/bluesound/media_player.py index 1e2a537cd62..1a633468a3a 100644 --- a/homeassistant/components/bluesound/media_player.py +++ b/homeassistant/components/bluesound/media_player.py @@ -493,6 +493,8 @@ class BluesoundPlayer(MediaPlayerEntity): return None position = self._status.seconds + if position is None: + return None if mediastate == MediaPlayerState.PLAYING: position += (dt_util.utcnow() - self._last_status_update).total_seconds() diff --git a/requirements_all.txt b/requirements_all.txt index 239c3c52f09..3688f912b49 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1780,7 +1780,7 @@ pybbox==0.0.5-alpha pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==1.0.3 +pyblu==1.0.4 # homeassistant.components.neato pybotvac==0.0.25 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1ee07086b28..e0fca2223bd 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1448,7 +1448,7 @@ pybalboa==1.0.2 pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==1.0.3 +pyblu==1.0.4 # homeassistant.components.neato pybotvac==0.0.25 From ca703cb858bb2404e6c5f14c9d66096766b7b3ac Mon Sep 17 00:00:00 2001 From: Petar Petrov Date: Thu, 17 Oct 2024 13:41:23 +0300 Subject: [PATCH 87/89] Increase Z-Wave fallback thermostat range to 0-50 C (#128543) * Z-Wave JS: Increase fallback thermostat range to 0-50 C * update test --- homeassistant/components/zwave_js/climate.py | 6 ++---- tests/components/zwave_js/test_climate.py | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zwave_js/climate.py b/homeassistant/components/zwave_js/climate.py index 14a3fe579c4..c7ab579c2cb 100644 --- a/homeassistant/components/zwave_js/climate.py +++ b/homeassistant/components/zwave_js/climate.py @@ -24,8 +24,6 @@ from homeassistant.components.climate import ( ATTR_HVAC_MODE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, - DEFAULT_MAX_TEMP, - DEFAULT_MIN_TEMP, DOMAIN as CLIMATE_DOMAIN, PRESET_NONE, ClimateEntity, @@ -421,7 +419,7 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): @property def min_temp(self) -> float: """Return the minimum temperature.""" - min_temp = DEFAULT_MIN_TEMP + min_temp = 0.0 # Not using DEFAULT_MIN_TEMP to allow wider range base_unit: str = UnitOfTemperature.CELSIUS try: temp = self._setpoint_value_or_raise(self._current_mode_setpoint_enums[0]) @@ -437,7 +435,7 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity): @property def max_temp(self) -> float: """Return the maximum temperature.""" - max_temp = DEFAULT_MAX_TEMP + max_temp = 50.0 # Not using DEFAULT_MAX_TEMP to allow wider range base_unit: str = UnitOfTemperature.CELSIUS try: temp = self._setpoint_value_or_raise(self._current_mode_setpoint_enums[0]) diff --git a/tests/components/zwave_js/test_climate.py b/tests/components/zwave_js/test_climate.py index 9a4559de1a5..5d711528a28 100644 --- a/tests/components/zwave_js/test_climate.py +++ b/tests/components/zwave_js/test_climate.py @@ -812,8 +812,8 @@ async def test_thermostat_heatit_z_trm2fx( | ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON ) - assert state.attributes[ATTR_MIN_TEMP] == 7 - assert state.attributes[ATTR_MAX_TEMP] == 35 + assert state.attributes[ATTR_MIN_TEMP] == 0 + assert state.attributes[ATTR_MAX_TEMP] == 50 # Try switching to external sensor event = Event( From e204812d2b8342e9fc772acdcd9affb9cd26905e Mon Sep 17 00:00:00 2001 From: mvn23 Date: Thu, 17 Oct 2024 18:57:22 +0200 Subject: [PATCH 88/89] Bump pyotgw to 2.2.2 (#128594) --- homeassistant/components/opentherm_gw/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opentherm_gw/manifest.json b/homeassistant/components/opentherm_gw/manifest.json index 927f9c9ca3e..ecd0a6b99d5 100644 --- a/homeassistant/components/opentherm_gw/manifest.json +++ b/homeassistant/components/opentherm_gw/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/opentherm_gw", "iot_class": "local_push", "loggers": ["pyotgw"], - "requirements": ["pyotgw==2.2.1"] + "requirements": ["pyotgw==2.2.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 3688f912b49..1400ed47f10 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2119,7 +2119,7 @@ pyoppleio-legacy==1.0.8 pyosoenergyapi==1.1.4 # homeassistant.components.opentherm_gw -pyotgw==2.2.1 +pyotgw==2.2.2 # homeassistant.auth.mfa_modules.notify # homeassistant.auth.mfa_modules.totp diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e0fca2223bd..dc41fc22d5a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1703,7 +1703,7 @@ pyopnsense==0.4.0 pyosoenergyapi==1.1.4 # homeassistant.components.opentherm_gw -pyotgw==2.2.1 +pyotgw==2.2.2 # homeassistant.auth.mfa_modules.notify # homeassistant.auth.mfa_modules.totp From 515771553f64ef99784a2e4e28123f5d5aa6a239 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 18 Oct 2024 13:22:48 +0200 Subject: [PATCH 89/89] Bump version to 2024.10.3 --- 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 b539cbc6068..62835ef723b 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2024 MINOR_VERSION: Final = 10 -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, 12, 0) diff --git a/pyproject.toml b/pyproject.toml index 5eb72a2b40e..dd50e28be98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2024.10.2" +version = "2024.10.3" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"