From 44808c02f9cc7b927559dc1098729fa5d4a8df41 Mon Sep 17 00:00:00 2001 From: Quentame Date: Wed, 8 Jan 2025 22:51:37 +0100 Subject: [PATCH 01/13] =?UTF-8?q?Fix=20M=C3=A9t=C3=A9o-France=20setup=20in?= =?UTF-8?q?=20non=20French=20cities=20(because=20of=20failed=20next=20rain?= =?UTF-8?q?=20sensor)=20(#134782)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homeassistant/components/meteo_france/__init__.py | 12 ++++++++++-- homeassistant/components/meteo_france/sensor.py | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/meteo_france/__init__.py b/homeassistant/components/meteo_france/__init__.py index 1d4f8293c5e..4b79b046b75 100644 --- a/homeassistant/components/meteo_france/__init__.py +++ b/homeassistant/components/meteo_france/__init__.py @@ -6,6 +6,7 @@ import logging from meteofrance_api.client import MeteoFranceClient from meteofrance_api.helpers import is_valid_warning_department from meteofrance_api.model import CurrentPhenomenons, Forecast, Rain +from requests import RequestException import voluptuous as vol from homeassistant.config_entries import ConfigEntry @@ -83,7 +84,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: update_method=_async_update_data_rain, update_interval=SCAN_INTERVAL_RAIN, ) - await coordinator_rain.async_config_entry_first_refresh() + try: + await coordinator_rain._async_refresh(log_failures=False) # noqa: SLF001 + except RequestException: + _LOGGER.warning( + "1 hour rain forecast not available: %s is not in covered zone", + entry.title, + ) department = coordinator_forecast.data.position.get("dept") _LOGGER.debug( @@ -128,8 +135,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.data[DOMAIN][entry.entry_id] = { UNDO_UPDATE_LISTENER: undo_listener, COORDINATOR_FORECAST: coordinator_forecast, - COORDINATOR_RAIN: coordinator_rain, } + if coordinator_rain and coordinator_rain.last_update_success: + hass.data[DOMAIN][entry.entry_id][COORDINATOR_RAIN] = coordinator_rain if coordinator_alert and coordinator_alert.last_update_success: hass.data[DOMAIN][entry.entry_id][COORDINATOR_ALERT] = coordinator_alert diff --git a/homeassistant/components/meteo_france/sensor.py b/homeassistant/components/meteo_france/sensor.py index d8dbdfc4265..826716f1679 100644 --- a/homeassistant/components/meteo_france/sensor.py +++ b/homeassistant/components/meteo_france/sensor.py @@ -187,7 +187,7 @@ async def async_setup_entry( """Set up the Meteo-France sensor platform.""" data = hass.data[DOMAIN][entry.entry_id] coordinator_forecast: DataUpdateCoordinator[Forecast] = data[COORDINATOR_FORECAST] - coordinator_rain: DataUpdateCoordinator[Rain] | None = data[COORDINATOR_RAIN] + coordinator_rain: DataUpdateCoordinator[Rain] | None = data.get(COORDINATOR_RAIN) coordinator_alert: DataUpdateCoordinator[CurrentPhenomenons] | None = data.get( COORDINATOR_ALERT ) From 2c02eefa119d3f64fe338646f6016b1d84aee9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Tue, 7 Jan 2025 13:18:02 +0100 Subject: [PATCH 02/13] Increase cloud backup download timeout (#134961) Increese download timeout --- homeassistant/components/cloud/backup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/cloud/backup.py b/homeassistant/components/cloud/backup.py index b9da6dfb6a4..632248224a2 100644 --- a/homeassistant/components/cloud/backup.py +++ b/homeassistant/components/cloud/backup.py @@ -138,7 +138,11 @@ class CloudBackupAgent(BackupAgent): raise BackupAgentError("Failed to get download details") from err try: - resp = await self._cloud.websession.get(details["url"]) + resp = await self._cloud.websession.get( + details["url"], + timeout=ClientTimeout(connect=10.0, total=43200.0), # 43200s == 12h + ) + resp.raise_for_status() except ClientError as err: raise BackupAgentError("Failed to download backup") from err From ab071d1c1bcafc8602dfb61e5df2b5a4e97c34f6 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Wed, 8 Jan 2025 04:51:57 -0500 Subject: [PATCH 03/13] Fix ZHA "referencing a non existing `via_device`" warning (#135008) --- homeassistant/components/zha/entity.py | 2 +- tests/components/zha/test_entity.py | 47 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/components/zha/test_entity.py diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index 3e3d0642ca2..77ba048312a 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -87,7 +87,7 @@ class ZHAEntity(LogMixin, RestoreEntity, Entity): manufacturer=zha_device_info[ATTR_MANUFACTURER], model=zha_device_info[ATTR_MODEL], name=zha_device_info[ATTR_NAME], - via_device=(DOMAIN, zha_gateway.state.node_info.ieee), + via_device=(DOMAIN, str(zha_gateway.state.node_info.ieee)), ) @callback diff --git a/tests/components/zha/test_entity.py b/tests/components/zha/test_entity.py new file mode 100644 index 00000000000..add98bb96bf --- /dev/null +++ b/tests/components/zha/test_entity.py @@ -0,0 +1,47 @@ +"""Test ZHA entities.""" + +from zigpy.profiles import zha +from zigpy.zcl.clusters import general + +from homeassistant.components.zha.helpers import get_zha_gateway +from homeassistant.core import HomeAssistant +from homeassistant.helpers import device_registry as dr + +from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE + + +async def test_device_registry_via_device( + hass: HomeAssistant, + setup_zha, + zigpy_device_mock, + device_registry: dr.DeviceRegistry, +) -> None: + """Test ZHA `via_device` is set correctly.""" + + await setup_zha() + gateway = get_zha_gateway(hass) + + zigpy_device = zigpy_device_mock( + { + 1: { + SIG_EP_INPUT: [general.Basic.cluster_id], + SIG_EP_OUTPUT: [], + SIG_EP_TYPE: zha.DeviceType.ON_OFF_SWITCH, + SIG_EP_PROFILE: zha.PROFILE_ID, + } + }, + ) + + zha_device = gateway.get_or_create_device(zigpy_device) + await gateway.async_device_initialized(zigpy_device) + await hass.async_block_till_done(wait_background_tasks=True) + + reg_coordinator_device = device_registry.async_get_device( + identifiers={("zha", str(gateway.state.node_info.ieee))} + ) + + reg_device = device_registry.async_get_device( + identifiers={("zha", str(zha_device.ieee))} + ) + + assert reg_device.via_device_id == reg_coordinator_device.id From 902bd57b4bb07fd3defdaa19410e1ba9dc463679 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Tue, 7 Jan 2025 20:24:39 +0100 Subject: [PATCH 04/13] Catch errors in automation (instead of raise unexpected error) in Overkiz (#135026) Catch errors in automation (instead of raise unexpected error) --- homeassistant/components/overkiz/executor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/overkiz/executor.py b/homeassistant/components/overkiz/executor.py index 02829eaf1a3..220c6fe7cb2 100644 --- a/homeassistant/components/overkiz/executor.py +++ b/homeassistant/components/overkiz/executor.py @@ -6,7 +6,7 @@ from typing import Any, cast from urllib.parse import urlparse from pyoverkiz.enums import OverkizCommand, Protocol -from pyoverkiz.exceptions import OverkizException +from pyoverkiz.exceptions import BaseOverkizException from pyoverkiz.models import Command, Device, StateDefinition from pyoverkiz.types import StateType as OverkizStateType @@ -105,7 +105,7 @@ class OverkizExecutor: "Home Assistant", ) # Catch Overkiz exceptions to support `continue_on_error` functionality - except OverkizException as exception: + except BaseOverkizException as exception: raise HomeAssistantError(exception) from exception # ExecutionRegisteredEvent doesn't contain the device_url, thus we need to register it here From 9601455d9f75822fc76806d7ca959cd62114f074 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Wed, 8 Jan 2025 09:28:01 +0100 Subject: [PATCH 05/13] Fix channel retrieval for Reolink DUO V1 connected to a NVR (#135035) fix channel retrieval for DUO V1 connected to a NVR --- homeassistant/components/reolink/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/reolink/util.py b/homeassistant/components/reolink/util.py index f52cb08286c..f10da8e4b96 100644 --- a/homeassistant/components/reolink/util.py +++ b/homeassistant/components/reolink/util.py @@ -82,7 +82,8 @@ def get_device_uid_and_ch( ch = int(device_uid[1][5:]) is_chime = True else: - ch = host.api.channel_for_uid(device_uid[1]) + device_uid_part = "_".join(device_uid[1:]) + ch = host.api.channel_for_uid(device_uid_part) return (device_uid, ch, is_chime) From 3c14e2f0a80e12da014ad13e70ed0099fcce8da3 Mon Sep 17 00:00:00 2001 From: Thomas55555 <59625598+Thomas55555@users.noreply.github.com> Date: Wed, 8 Jan 2025 09:26:48 +0100 Subject: [PATCH 06/13] Bump aioautomower to 2025.1.0 (#135039) --- 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 02e87a3a772..1eed2be4575 100644 --- a/homeassistant/components/husqvarna_automower/manifest.json +++ b/homeassistant/components/husqvarna_automower/manifest.json @@ -8,5 +8,5 @@ "iot_class": "cloud_push", "loggers": ["aioautomower"], "quality_scale": "silver", - "requirements": ["aioautomower==2024.12.0"] + "requirements": ["aioautomower==2025.1.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index e64a48cbb81..713c8ac2ab4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -201,7 +201,7 @@ aioaseko==1.0.0 aioasuswrt==1.4.0 # homeassistant.components.husqvarna_automower -aioautomower==2024.12.0 +aioautomower==2025.1.0 # homeassistant.components.azure_devops aioazuredevops==2.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index bf0bcb7f9d3..6567f4ea4ec 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -189,7 +189,7 @@ aioaseko==1.0.0 aioasuswrt==1.4.0 # homeassistant.components.husqvarna_automower -aioautomower==2024.12.0 +aioautomower==2025.1.0 # homeassistant.components.azure_devops aioazuredevops==2.2.1 From 7f3f550b7bcb9763f39bafad9061fe78fce707f4 Mon Sep 17 00:00:00 2001 From: Cyrill Raccaud Date: Wed, 8 Jan 2025 09:24:09 +0100 Subject: [PATCH 07/13] Bump cookidoo-api to 0.12.2 (#135045) fix cookidoo .co.uk countries and group api endpoint --- homeassistant/components/cookidoo/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/cookidoo/manifest.json b/homeassistant/components/cookidoo/manifest.json index b1a3e9c0267..5264e47a709 100644 --- a/homeassistant/components/cookidoo/manifest.json +++ b/homeassistant/components/cookidoo/manifest.json @@ -8,5 +8,5 @@ "iot_class": "cloud_polling", "loggers": ["cookidoo_api"], "quality_scale": "silver", - "requirements": ["cookidoo-api==0.11.2"] + "requirements": ["cookidoo-api==0.12.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 713c8ac2ab4..23189df493d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -704,7 +704,7 @@ connect-box==0.3.1 construct==2.10.68 # homeassistant.components.cookidoo -cookidoo-api==0.11.2 +cookidoo-api==0.12.2 # homeassistant.components.backup # homeassistant.components.utility_meter diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6567f4ea4ec..ad17b89cd0a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -600,7 +600,7 @@ colorthief==0.2.1 construct==2.10.68 # homeassistant.components.cookidoo -cookidoo-api==0.11.2 +cookidoo-api==0.12.2 # homeassistant.components.backup # homeassistant.components.utility_meter From b8b7daff5aa2746b7295b86ae01d89effc4f2846 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 9 Jan 2025 22:23:53 +0100 Subject: [PATCH 08/13] Implement upload retry logic in CloudBackupAgent (#135062) * Implement upload retry logic in CloudBackupAgent * Update backup.py Co-authored-by: Erik Montnemery * nit --------- Co-authored-by: Erik Montnemery --- homeassistant/components/cloud/backup.py | 97 +++++++++++++++++------- tests/components/cloud/test_backup.py | 7 ++ 2 files changed, 77 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/cloud/backup.py b/homeassistant/components/cloud/backup.py index 632248224a2..f94a3a0ff49 100644 --- a/homeassistant/components/cloud/backup.py +++ b/homeassistant/components/cloud/backup.py @@ -2,10 +2,12 @@ from __future__ import annotations +import asyncio import base64 from collections.abc import AsyncIterator, Callable, Coroutine, Mapping import hashlib import logging +import random from typing import Any, Self from aiohttp import ClientError, ClientTimeout, StreamReader @@ -26,6 +28,9 @@ from .const import DATA_CLOUD, DOMAIN, EVENT_CLOUD_EVENT _LOGGER = logging.getLogger(__name__) _STORAGE_BACKUP = "backup" +_RETRY_LIMIT = 5 +_RETRY_SECONDS_MIN = 60 +_RETRY_SECONDS_MAX = 600 async def _b64md5(stream: AsyncIterator[bytes]) -> str: @@ -149,6 +154,44 @@ class CloudBackupAgent(BackupAgent): return ChunkAsyncStreamIterator(resp.content) + async def _async_do_upload_backup( + self, + *, + open_stream: Callable[[], Coroutine[Any, Any, AsyncIterator[bytes]]], + filename: str, + base64md5hash: str, + metadata: dict[str, Any], + size: int, + ) -> None: + """Upload a backup.""" + try: + details = await async_files_upload_details( + self._cloud, + storage_type=_STORAGE_BACKUP, + filename=filename, + metadata=metadata, + size=size, + base64md5hash=base64md5hash, + ) + except (ClientError, CloudError) as err: + raise BackupAgentError("Failed to get upload details") from err + + try: + upload_status = await self._cloud.websession.put( + details["url"], + data=await open_stream(), + headers=details["headers"] | {"content-length": str(size)}, + timeout=ClientTimeout(connect=10.0, total=43200.0), # 43200s == 12h + ) + _LOGGER.log( + logging.DEBUG if upload_status.status < 400 else logging.WARNING, + "Backup upload status: %s", + upload_status.status, + ) + upload_status.raise_for_status() + except (TimeoutError, ClientError) as err: + raise BackupAgentError("Failed to upload backup") from err + async def async_upload_backup( self, *, @@ -165,34 +208,34 @@ class CloudBackupAgent(BackupAgent): raise BackupAgentError("Cloud backups must be protected") base64md5hash = await _b64md5(await open_stream()) + filename = self._get_backup_filename() + metadata = backup.as_dict() + size = backup.size - try: - details = await async_files_upload_details( - self._cloud, - storage_type=_STORAGE_BACKUP, - filename=self._get_backup_filename(), - metadata=backup.as_dict(), - size=backup.size, - base64md5hash=base64md5hash, - ) - except (ClientError, CloudError) as err: - raise BackupAgentError("Failed to get upload details") from err - - try: - upload_status = await self._cloud.websession.put( - details["url"], - data=await open_stream(), - headers=details["headers"] | {"content-length": str(backup.size)}, - timeout=ClientTimeout(connect=10.0, total=43200.0), # 43200s == 12h - ) - _LOGGER.log( - logging.DEBUG if upload_status.status < 400 else logging.WARNING, - "Backup upload status: %s", - upload_status.status, - ) - upload_status.raise_for_status() - except (TimeoutError, ClientError) as err: - raise BackupAgentError("Failed to upload backup") from err + tries = 1 + while tries <= _RETRY_LIMIT: + try: + await self._async_do_upload_backup( + open_stream=open_stream, + filename=filename, + base64md5hash=base64md5hash, + metadata=metadata, + size=size, + ) + break + except BackupAgentError as err: + if tries == _RETRY_LIMIT: + raise + tries += 1 + retry_timer = random.randint(_RETRY_SECONDS_MIN, _RETRY_SECONDS_MAX) + _LOGGER.info( + "Failed to upload backup, retrying (%s/%s) in %ss: %s", + tries, + _RETRY_LIMIT, + retry_timer, + err, + ) + await asyncio.sleep(retry_timer) async def async_delete_backup( self, diff --git a/tests/components/cloud/test_backup.py b/tests/components/cloud/test_backup.py index 5d9513a1d1b..fc8c7f27e56 100644 --- a/tests/components/cloud/test_backup.py +++ b/tests/components/cloud/test_backup.py @@ -389,6 +389,7 @@ async def test_agents_upload_fail_put( aioclient_mock: AiohttpClientMocker, mock_get_upload_details: Mock, put_mock_kwargs: dict[str, Any], + caplog: pytest.LogCaptureFixture, ) -> None: """Test agent upload backup fails.""" client = await hass_client() @@ -417,6 +418,9 @@ async def test_agents_upload_fail_put( return_value=test_backup, ), patch("pathlib.Path.open") as mocked_open, + patch("homeassistant.components.cloud.backup.asyncio.sleep"), + patch("homeassistant.components.cloud.backup.random.randint", return_value=60), + patch("homeassistant.components.cloud.backup._RETRY_LIMIT", 2), ): mocked_open.return_value.read = Mock(side_effect=[b"test", b""]) fetch_backup.return_value = test_backup @@ -426,6 +430,8 @@ async def test_agents_upload_fail_put( ) await hass.async_block_till_done() + assert len(aioclient_mock.mock_calls) == 2 + assert "Failed to upload backup, retrying (2/2) in 60s" in caplog.text assert resp.status == 201 store_backups = hass_storage[BACKUP_DOMAIN]["data"]["backups"] assert len(store_backups) == 1 @@ -469,6 +475,7 @@ async def test_agents_upload_fail_cloud( return_value=test_backup, ), patch("pathlib.Path.open") as mocked_open, + patch("homeassistant.components.cloud.backup.asyncio.sleep"), ): mocked_open.return_value.read = Mock(side_effect=[b"test", b""]) fetch_backup.return_value = test_backup From 42cdd25d908978c5a879033ef8abbc7a20820d0c Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 9 Jan 2025 10:53:33 +0100 Subject: [PATCH 09/13] Add jitter to backup start time to avoid thundering herd (#135065) --- homeassistant/components/backup/config.py | 7 +++++++ tests/components/backup/test_websocket.py | 2 ++ 2 files changed, 9 insertions(+) diff --git a/homeassistant/components/backup/config.py b/homeassistant/components/backup/config.py index 3c5d5d39f7e..7c40792aec5 100644 --- a/homeassistant/components/backup/config.py +++ b/homeassistant/components/backup/config.py @@ -7,6 +7,7 @@ from collections.abc import Callable from dataclasses import dataclass, field, replace from datetime import datetime, timedelta from enum import StrEnum +import random from typing import TYPE_CHECKING, Self, TypedDict from cronsim import CronSim @@ -28,6 +29,10 @@ if TYPE_CHECKING: CRON_PATTERN_DAILY = "45 4 * * *" CRON_PATTERN_WEEKLY = "45 4 * * {}" +# Randomize the start time of the backup by up to 60 minutes to avoid +# all backups running at the same time. +BACKUP_START_TIME_JITTER = 60 * 60 + class StoredBackupConfig(TypedDict): """Represent the stored backup config.""" @@ -329,6 +334,8 @@ class BackupSchedule: except Exception: # noqa: BLE001 LOGGER.exception("Unexpected error creating automatic backup") + next_time += timedelta(seconds=random.randint(0, BACKUP_START_TIME_JITTER)) + LOGGER.debug("Scheduling next automatic backup at %s", next_time) manager.remove_next_backup_event = async_track_point_in_time( manager.hass, _create_backup, next_time ) diff --git a/tests/components/backup/test_websocket.py b/tests/components/backup/test_websocket.py index 307a1d79e0c..e95481373d6 100644 --- a/tests/components/backup/test_websocket.py +++ b/tests/components/backup/test_websocket.py @@ -1345,6 +1345,7 @@ async def test_config_update_errors( ), ], ) +@patch("homeassistant.components.backup.config.BACKUP_START_TIME_JITTER", 0) async def test_config_schedule_logic( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, @@ -1787,6 +1788,7 @@ async def test_config_schedule_logic( ), ], ) +@patch("homeassistant.components.backup.config.BACKUP_START_TIME_JITTER", 0) async def test_config_retention_copies_logic( hass: HomeAssistant, hass_ws_client: WebSocketGenerator, From 1eddb4a21b4cc7a2251736f2d0a7055859c9ecbd Mon Sep 17 00:00:00 2001 From: jb101010-2 <168106462+jb101010-2@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:12:56 +0100 Subject: [PATCH 10/13] Bump pysuezV2 to 2.0.3 (#135080) --- homeassistant/components/suez_water/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/suez_water/manifest.json b/homeassistant/components/suez_water/manifest.json index 176b059f3d5..5d317ea5ba3 100644 --- a/homeassistant/components/suez_water/manifest.json +++ b/homeassistant/components/suez_water/manifest.json @@ -7,5 +7,5 @@ "iot_class": "cloud_polling", "loggers": ["pysuez", "regex"], "quality_scale": "bronze", - "requirements": ["pysuezV2==2.0.1"] + "requirements": ["pysuezV2==2.0.3"] } diff --git a/requirements_all.txt b/requirements_all.txt index 23189df493d..18804643b7c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2309,7 +2309,7 @@ pysqueezebox==0.10.0 pystiebeleltron==0.0.1.dev2 # homeassistant.components.suez_water -pysuezV2==2.0.1 +pysuezV2==2.0.3 # homeassistant.components.switchbee pyswitchbee==1.8.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ad17b89cd0a..469ff2cbe19 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1875,7 +1875,7 @@ pyspeex-noise==1.0.2 pysqueezebox==0.10.0 # homeassistant.components.suez_water -pysuezV2==2.0.1 +pysuezV2==2.0.3 # homeassistant.components.switchbee pyswitchbee==1.8.3 From 30924b561a8d9d2e109457ce19c7b6945b4bc208 Mon Sep 17 00:00:00 2001 From: Brynley McDonald Date: Thu, 9 Jan 2025 22:09:04 +1300 Subject: [PATCH 11/13] Fix Flick Electric Pricing (#135154) --- homeassistant/components/flick_electric/manifest.json | 2 +- homeassistant/components/flick_electric/sensor.py | 6 +++--- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/flick_electric/manifest.json b/homeassistant/components/flick_electric/manifest.json index 3aee25995a9..3096590f47a 100644 --- a/homeassistant/components/flick_electric/manifest.json +++ b/homeassistant/components/flick_electric/manifest.json @@ -7,5 +7,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "loggers": ["pyflick"], - "requirements": ["PyFlick==1.1.2"] + "requirements": ["PyFlick==1.1.3"] } diff --git a/homeassistant/components/flick_electric/sensor.py b/homeassistant/components/flick_electric/sensor.py index 147d00c943d..73b6f8793fb 100644 --- a/homeassistant/components/flick_electric/sensor.py +++ b/homeassistant/components/flick_electric/sensor.py @@ -51,19 +51,19 @@ class FlickPricingSensor(CoordinatorEntity[FlickElectricDataCoordinator], Sensor _LOGGER.warning( "Unexpected quantity for unit price: %s", self.coordinator.data ) - return self.coordinator.data.cost + return self.coordinator.data.cost * 100 @property def extra_state_attributes(self) -> dict[str, Any] | None: """Return the state attributes.""" - components: dict[str, Decimal] = {} + components: dict[str, float] = {} for component in self.coordinator.data.components: if component.charge_setter not in ATTR_COMPONENTS: _LOGGER.warning("Found unknown component: %s", component.charge_setter) continue - components[component.charge_setter] = component.value + components[component.charge_setter] = float(component.value * 100) return { ATTR_START_AT: self.coordinator.data.start_at, diff --git a/requirements_all.txt b/requirements_all.txt index 18804643b7c..92172aec637 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -48,7 +48,7 @@ ProgettiHWSW==0.1.3 PyChromecast==14.0.5 # homeassistant.components.flick_electric -PyFlick==1.1.2 +PyFlick==1.1.3 # homeassistant.components.flume PyFlume==0.6.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 469ff2cbe19..055fc3700a1 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -45,7 +45,7 @@ ProgettiHWSW==0.1.3 PyChromecast==14.0.5 # homeassistant.components.flick_electric -PyFlick==1.1.2 +PyFlick==1.1.3 # homeassistant.components.flume PyFlume==0.6.5 From 5d201406cb10c0bfbd3b3969a9c4a1869bd59442 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 9 Jan 2025 22:13:39 +0100 Subject: [PATCH 12/13] Update frontend to 20250109.0 (#135235) --- 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 267374aa302..3d9f12bd3d3 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -21,5 +21,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20250106.0"] + "requirements": ["home-assistant-frontend==20250109.0"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index dac77fd4276..3d9ecdece06 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -35,7 +35,7 @@ habluetooth==3.7.0 hass-nabucasa==0.87.0 hassil==2.1.0 home-assistant-bluetooth==1.13.0 -home-assistant-frontend==20250106.0 +home-assistant-frontend==20250109.0 home-assistant-intents==2025.1.1 httpx==0.27.2 ifaddr==0.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index 92172aec637..f11d3b691e3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1134,7 +1134,7 @@ hole==0.8.0 holidays==0.64 # homeassistant.components.frontend -home-assistant-frontend==20250106.0 +home-assistant-frontend==20250109.0 # homeassistant.components.conversation home-assistant-intents==2025.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 055fc3700a1..11260d55e59 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -963,7 +963,7 @@ hole==0.8.0 holidays==0.64 # homeassistant.components.frontend -home-assistant-frontend==20250106.0 +home-assistant-frontend==20250109.0 # homeassistant.components.conversation home-assistant-intents==2025.1.1 From 0027d907a410097db6cd24386feb415efebb8e79 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 9 Jan 2025 22:25:42 +0100 Subject: [PATCH 13/13] Bump version to 2025.1.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 e641ae4254c..9f25ff3f80a 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -25,7 +25,7 @@ if TYPE_CHECKING: APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2025 MINOR_VERSION: Final = 1 -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 f94d54feb88..4d88c5641fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2025.1.1" +version = "2025.1.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"