From f325122da5ee9a54f54cba84adec1a1880a8c26b Mon Sep 17 00:00:00 2001 From: uvjustin <46082645+uvjustin@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:54:54 +0800 Subject: [PATCH 001/120] Raise PlatformNotReady on initial OwnTone connection failure (#97257) --- .../components/forked_daapd/__init__.py | 5 +++-- .../components/forked_daapd/media_player.py | 6 ++++-- .../forked_daapd/test_config_flow.py | 19 ++++++++++++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/forked_daapd/__init__.py b/homeassistant/components/forked_daapd/__init__.py index 14f40db2057..9dfb92c60c8 100644 --- a/homeassistant/components/forked_daapd/__init__.py +++ b/homeassistant/components/forked_daapd/__init__.py @@ -18,9 +18,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Remove forked-daapd component.""" status = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) if status and hass.data.get(DOMAIN) and hass.data[DOMAIN].get(entry.entry_id): - hass.data[DOMAIN][entry.entry_id][ + if websocket_handler := hass.data[DOMAIN][entry.entry_id][ HASS_DATA_UPDATER_KEY - ].websocket_handler.cancel() + ].websocket_handler: + websocket_handler.cancel() for remove_listener in hass.data[DOMAIN][entry.entry_id][ HASS_DATA_REMOVE_LISTENERS_KEY ]: diff --git a/homeassistant/components/forked_daapd/media_player.py b/homeassistant/components/forked_daapd/media_player.py index e1f1ece055b..868ec8e1f9e 100644 --- a/homeassistant/components/forked_daapd/media_player.py +++ b/homeassistant/components/forked_daapd/media_player.py @@ -31,6 +31,7 @@ from homeassistant.components.spotify import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import PlatformNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, @@ -127,10 +128,10 @@ async def async_setup_entry( forked_daapd_updater = ForkedDaapdUpdater( hass, forked_daapd_api, config_entry.entry_id ) - await forked_daapd_updater.async_init() hass.data[DOMAIN][config_entry.entry_id][ HASS_DATA_UPDATER_KEY ] = forked_daapd_updater + await forked_daapd_updater.async_init() async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: @@ -914,7 +915,8 @@ class ForkedDaapdUpdater: async def async_init(self): """Perform async portion of class initialization.""" - server_config = await self._api.get_request("config") + if not (server_config := await self._api.get_request("config")): + raise PlatformNotReady if websocket_port := server_config.get("websocket_port"): self.websocket_handler = asyncio.create_task( self._api.start_websocket_handler( diff --git a/tests/components/forked_daapd/test_config_flow.py b/tests/components/forked_daapd/test_config_flow.py index 81357b6f3eb..fc02cdb4123 100644 --- a/tests/components/forked_daapd/test_config_flow.py +++ b/tests/components/forked_daapd/test_config_flow.py @@ -1,5 +1,5 @@ """The config flow tests for the forked_daapd media player platform.""" -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -12,9 +12,11 @@ from homeassistant.components.forked_daapd.const import ( CONF_TTS_VOLUME, DOMAIN, ) +from homeassistant.components.forked_daapd.media_player import async_setup_entry from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT from homeassistant.core import HomeAssistant +from homeassistant.exceptions import PlatformNotReady from tests.common import MockConfigEntry @@ -242,3 +244,18 @@ async def test_options_flow(hass: HomeAssistant, config_entry) -> None: }, ) assert result["type"] == data_entry_flow.FlowResultType.CREATE_ENTRY + + +async def test_async_setup_entry_not_ready(hass: HomeAssistant, config_entry) -> None: + """Test that a PlatformNotReady exception is thrown during platform setup.""" + + with patch( + "homeassistant.components.forked_daapd.media_player.ForkedDaapdAPI", + autospec=True, + ) as mock_api: + mock_api.return_value.get_request.return_value = None + config_entry.add_to_hass(hass) + with pytest.raises(PlatformNotReady): + await async_setup_entry(hass, config_entry, MagicMock()) + await hass.async_block_till_done() + mock_api.return_value.get_request.assert_called_once() From 77eec53f63949a6ebaa7db643d60bbbf9095c954 Mon Sep 17 00:00:00 2001 From: Matthieu Barthelemy Date: Fri, 4 Aug 2023 11:50:03 +0200 Subject: [PATCH 002/120] Add overkiz battery sensor level medium (#97472) --- homeassistant/components/overkiz/sensor.py | 2 +- homeassistant/components/overkiz/strings.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/overkiz/sensor.py b/homeassistant/components/overkiz/sensor.py index c841e3b0e36..b5296d772df 100644 --- a/homeassistant/components/overkiz/sensor.py +++ b/homeassistant/components/overkiz/sensor.py @@ -67,7 +67,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [ entity_category=EntityCategory.DIAGNOSTIC, icon="mdi:battery", device_class=SensorDeviceClass.ENUM, - options=["full", "normal", "low", "verylow"], + options=["full", "normal", "medium", "low", "verylow"], translation_key="battery", ), OverkizSensorDescription( diff --git a/homeassistant/components/overkiz/strings.json b/homeassistant/components/overkiz/strings.json index c4daf32499a..bcf1e121f6f 100644 --- a/homeassistant/components/overkiz/strings.json +++ b/homeassistant/components/overkiz/strings.json @@ -77,6 +77,7 @@ "full": "Full", "low": "Low", "normal": "Normal", + "medium": "Medium", "verylow": "Very low" } }, From 21f878bfa4c608bdba7f7dfc265f0f8190b5cb65 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Thu, 3 Aug 2023 21:20:40 +0200 Subject: [PATCH 003/120] Fix ZHA `turn_on` issues with `transition=0`, improve tests (#97539) * Fix turn_on ignoring transition=0 and brightness=None, add test This fixes light.turn_on for ZHA lights ignoring a transition of 0 when no brightness is given at the same time. It also adds a test for that case. Fixes https://github.com/home-assistant/core/issues/93265 * Add test for "force on" lights This test checks that "force on" lights also get an "on" command (in addition to the "move to level" command) when turn_on is called with only transition=0. * Fix "on" command sent for transition=0 calls, fix FORCE_ON missing for transition=0 This fixes an issue where the "on" command is sent in addition to a "move_to_level_with_on_off" command, even though the latter one is enough (for non-FORCE_ON lights). It also fixes the test to not expect the unnecessary "on" command (in addition to the expected "move_to_level_with_on_off" command). The `brightness != 0` change is needed to fix an issue where FORCE_ON lights did not get the required "on" command (in addition to "move_to_level_with_on_off") if turn_on was called with only transition=0. (It could have been `brightness not None`, but that would also send an "on" command if turn_on is called with brightness=0 which HA somewhat "supports". The brightness != 0 check avoids that issue.) * Improve comments in ZHA light class --- homeassistant/components/zha/light.py | 12 ++-- tests/components/zha/test_light.py | 85 +++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 9e71691aaa5..73955614c07 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -329,7 +329,7 @@ class BaseLight(LogMixin, light.LightEntity): return if ( - (brightness is not None or transition) + (brightness is not None or transition is not None) and not new_color_provided_while_off and brightness_supported(self._attr_supported_color_modes) ): @@ -350,11 +350,11 @@ class BaseLight(LogMixin, light.LightEntity): self._attr_brightness = level if ( - brightness is None + (brightness is None and transition is None) and not new_color_provided_while_off - or (self._FORCE_ON and brightness) + or (self._FORCE_ON and brightness != 0) ): - # since some lights don't always turn on with move_to_level_with_on_off, + # since FORCE_ON lights don't turn on with move_to_level_with_on_off, # we should call the on command on the on_off cluster # if brightness is not 0. result = await self._on_off_cluster_handler.on() @@ -385,7 +385,7 @@ class BaseLight(LogMixin, light.LightEntity): return if new_color_provided_while_off: - # The light is has the correct color, so we can now transition + # The light has the correct color, so we can now transition # it to the correct brightness level. result = await self._level_cluster_handler.move_to_level( level=level, transition_time=int(10 * duration) @@ -1076,7 +1076,7 @@ class HueLight(Light): manufacturers={"Jasco", "Quotra-Vision", "eWeLight", "eWeLink"}, ) class ForceOnLight(Light): - """Representation of a light which does not respect move_to_level_with_on_off.""" + """Representation of a light which does not respect on/off for move_to_level_with_on_off commands.""" _attr_name: str = "Light" _FORCE_ON = True diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py index 3abfd0e4f9c..c1f5cf04e35 100644 --- a/tests/components/zha/test_light.py +++ b/tests/components/zha/test_light.py @@ -530,7 +530,78 @@ async def test_transitions( light2_state = hass.states.get(device_2_entity_id) assert light2_state.state == STATE_OFF - # first test 0 length transition with no color provided + # first test 0 length transition with no color and no brightness provided + dev1_cluster_on_off.request.reset_mock() + dev1_cluster_level.request.reset_mock() + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": device_1_entity_id, "transition": 0}, + blocking=True, + ) + assert dev1_cluster_on_off.request.call_count == 0 + assert dev1_cluster_on_off.request.await_count == 0 + assert dev1_cluster_color.request.call_count == 0 + assert dev1_cluster_color.request.await_count == 0 + assert dev1_cluster_level.request.call_count == 1 + assert dev1_cluster_level.request.await_count == 1 + assert dev1_cluster_level.request.call_args == call( + False, + dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].id, + dev1_cluster_level.commands_by_name["move_to_level_with_on_off"].schema, + level=254, # default "full on" brightness + transition_time=0, + expect_reply=True, + manufacturer=None, + tsn=None, + ) + + light1_state = hass.states.get(device_1_entity_id) + assert light1_state.state == STATE_ON + assert light1_state.attributes["brightness"] == 254 + + # test 0 length transition with no color and no brightness provided again, but for "force on" lights + eWeLink_cluster_on_off.request.reset_mock() + eWeLink_cluster_level.request.reset_mock() + await hass.services.async_call( + LIGHT_DOMAIN, + "turn_on", + {"entity_id": eWeLink_light_entity_id, "transition": 0}, + blocking=True, + ) + assert eWeLink_cluster_on_off.request.call_count == 1 + assert eWeLink_cluster_on_off.request.await_count == 1 + assert eWeLink_cluster_on_off.request.call_args_list[0] == call( + False, + eWeLink_cluster_on_off.commands_by_name["on"].id, + eWeLink_cluster_on_off.commands_by_name["on"].schema, + expect_reply=True, + manufacturer=None, + tsn=None, + ) + assert eWeLink_cluster_color.request.call_count == 0 + assert eWeLink_cluster_color.request.await_count == 0 + assert eWeLink_cluster_level.request.call_count == 1 + assert eWeLink_cluster_level.request.await_count == 1 + assert eWeLink_cluster_level.request.call_args == call( + False, + eWeLink_cluster_level.commands_by_name["move_to_level_with_on_off"].id, + eWeLink_cluster_level.commands_by_name["move_to_level_with_on_off"].schema, + level=254, # default "full on" brightness + transition_time=0, + expect_reply=True, + manufacturer=None, + tsn=None, + ) + + eWeLink_state = hass.states.get(eWeLink_light_entity_id) + assert eWeLink_state.state == STATE_ON + assert eWeLink_state.attributes["brightness"] == 254 + + eWeLink_cluster_on_off.request.reset_mock() + eWeLink_cluster_level.request.reset_mock() + + # test 0 length transition with brightness, but no color provided dev1_cluster_on_off.request.reset_mock() dev1_cluster_level.request.reset_mock() await hass.services.async_call( @@ -1423,18 +1494,10 @@ async def async_test_level_on_off_from_hass( {"entity_id": entity_id, "transition": 10}, blocking=True, ) - assert on_off_cluster.request.call_count == 1 - assert on_off_cluster.request.await_count == 1 + assert on_off_cluster.request.call_count == 0 + assert on_off_cluster.request.await_count == 0 assert level_cluster.request.call_count == 1 assert level_cluster.request.await_count == 1 - assert on_off_cluster.request.call_args == call( - False, - on_off_cluster.commands_by_name["on"].id, - on_off_cluster.commands_by_name["on"].schema, - expect_reply=True, - manufacturer=None, - tsn=None, - ) assert level_cluster.request.call_args == call( False, level_cluster.commands_by_name["move_to_level_with_on_off"].id, From b6671385bcffa771941346e6994e4c4c68dba4ed Mon Sep 17 00:00:00 2001 From: Maikel Punie Date: Wed, 2 Aug 2023 08:23:37 +0200 Subject: [PATCH 004/120] Bump pyDuotecno to 2023.8.1 (#97583) --- 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 ae82574146e..c0bd29547c5 100644 --- a/homeassistant/components/duotecno/manifest.json +++ b/homeassistant/components/duotecno/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/duotecno", "iot_class": "local_push", - "requirements": ["pyduotecno==2023.8.0"] + "requirements": ["pyduotecno==2023.8.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 28140477411..4d18091e019 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1650,7 +1650,7 @@ pydrawise==2023.7.1 pydroid-ipcam==2.0.0 # homeassistant.components.duotecno -pyduotecno==2023.8.0 +pyduotecno==2023.8.1 # homeassistant.components.ebox pyebox==1.1.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 03dc3bbf994..59a8a20f185 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1223,7 +1223,7 @@ pydiscovergy==2.0.1 pydroid-ipcam==2.0.0 # homeassistant.components.duotecno -pyduotecno==2023.8.0 +pyduotecno==2023.8.1 # homeassistant.components.econet pyeconet==0.1.20 From 20bddec328861915beca056a2863cd049af7a524 Mon Sep 17 00:00:00 2001 From: Blastoise186 <40033667+blastoise186@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:36:12 +0100 Subject: [PATCH 005/120] Bump Cryptography to 41.0.3 for a second security fix (#97611) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- 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 7401c747890..615e5fa9444 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -15,7 +15,7 @@ bluetooth-auto-recovery==1.2.1 bluetooth-data-tools==1.6.1 certifi>=2021.5.30 ciso8601==2.3.0 -cryptography==41.0.2 +cryptography==41.0.3 dbus-fast==1.87.5 fnv-hash-fast==0.4.0 ha-av==10.1.1 diff --git a/pyproject.toml b/pyproject.toml index 26a9525a176..e4e8fab4b15 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,7 +41,7 @@ dependencies = [ "lru-dict==1.2.0", "PyJWT==2.8.0", # PyJWT has loose dependency. We want the latest one. - "cryptography==41.0.2", + "cryptography==41.0.3", # pyOpenSSL 23.2.0 is required to work with cryptography 41+ "pyOpenSSL==23.2.0", "orjson==3.9.2", diff --git a/requirements.txt b/requirements.txt index 9f5023c9a1c..4106a8515d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,7 @@ ifaddr==0.2.0 Jinja2==3.1.2 lru-dict==1.2.0 PyJWT==2.8.0 -cryptography==41.0.2 +cryptography==41.0.3 pyOpenSSL==23.2.0 orjson==3.9.2 pip>=21.3.1 From c5747dffbc55f4aa65fcfea373d4f8e44a75c059 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 4 Aug 2023 08:45:36 +0200 Subject: [PATCH 006/120] Waqi State unknown if value is string (#97617) --- homeassistant/components/waqi/sensor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/waqi/sensor.py b/homeassistant/components/waqi/sensor.py index e91e3da5aa5..ae4e46c2a0b 100644 --- a/homeassistant/components/waqi/sensor.py +++ b/homeassistant/components/waqi/sensor.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio +from contextlib import suppress from datetime import timedelta import logging @@ -141,8 +142,9 @@ class WaqiSensor(SensorEntity): @property def native_value(self): """Return the state of the device.""" - if self._data is not None: - return self._data.get("aqi") + if value := self._data.get("aqi"): + with suppress(ValueError): + return float(value) return None @property From 72533ad292f8387b886f359119369dc662af66a9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 01:33:05 -1000 Subject: [PATCH 007/120] Bump dbus-fast to 1.90.1 (#97619) * Bump dbus-fast to 1.88.0 - cython 3 fixes - performance improvements changelog: https://github.com/Bluetooth-Devices/dbus-fast/compare/v1.87.5...v1.88.0 * one more * Bump dbus-fast to 1.90.0 * bump again for yet another round of cython3 fixes --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index bc07e2b94ae..67c27f014d1 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -19,6 +19,6 @@ "bluetooth-adapters==0.16.0", "bluetooth-auto-recovery==1.2.1", "bluetooth-data-tools==1.6.1", - "dbus-fast==1.87.5" + "dbus-fast==1.90.1" ] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 615e5fa9444..618b284a619 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -16,7 +16,7 @@ bluetooth-data-tools==1.6.1 certifi>=2021.5.30 ciso8601==2.3.0 cryptography==41.0.3 -dbus-fast==1.87.5 +dbus-fast==1.90.1 fnv-hash-fast==0.4.0 ha-av==10.1.1 hass-nabucasa==0.69.0 diff --git a/requirements_all.txt b/requirements_all.txt index 4d18091e019..f656ca2bba9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -632,7 +632,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus-fast==1.87.5 +dbus-fast==1.90.1 # homeassistant.components.debugpy debugpy==1.6.7 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 59a8a20f185..89496b540c0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -515,7 +515,7 @@ datadog==0.15.0 datapoint==0.9.8 # homeassistant.components.bluetooth -dbus-fast==1.87.5 +dbus-fast==1.90.1 # homeassistant.components.debugpy debugpy==1.6.7 From 62421d9ec3e50eefb288a9a4c348d0e4ef204e31 Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 3 Aug 2023 06:15:20 -0400 Subject: [PATCH 008/120] Bump python-roborock to 0.31.1 (#97632) bump to 0.31.1 --- homeassistant/components/roborock/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index d26116a7818..eda6a5609a2 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/roborock", "iot_class": "local_polling", "loggers": ["roborock"], - "requirements": ["python-roborock==0.30.2"] + "requirements": ["python-roborock==0.31.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index f656ca2bba9..2a2f0d1aa20 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2150,7 +2150,7 @@ python-qbittorrent==0.4.3 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==0.30.2 +python-roborock==0.31.1 # homeassistant.components.smarttub python-smarttub==0.0.33 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 89496b540c0..de45c832370 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1579,7 +1579,7 @@ python-picnic-api==1.1.0 python-qbittorrent==0.4.3 # homeassistant.components.roborock -python-roborock==0.30.2 +python-roborock==0.31.1 # homeassistant.components.smarttub python-smarttub==0.0.33 From 455ac084ece466eb657c0a745883b8e46033a0b1 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Wed, 2 Aug 2023 19:01:30 -0500 Subject: [PATCH 009/120] Bump intents to 2023.8.2 (#97636) --- homeassistant/components/conversation/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/conversation/snapshots/test_init.ambr | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/conversation/manifest.json b/homeassistant/components/conversation/manifest.json index 1eb58e96ff9..9e0909b6dfc 100644 --- a/homeassistant/components/conversation/manifest.json +++ b/homeassistant/components/conversation/manifest.json @@ -7,5 +7,5 @@ "integration_type": "system", "iot_class": "local_push", "quality_scale": "internal", - "requirements": ["hassil==1.2.5", "home-assistant-intents==2023.7.25"] + "requirements": ["hassil==1.2.5", "home-assistant-intents==2023.8.2"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 618b284a619..6564dfb3a0d 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -23,7 +23,7 @@ hass-nabucasa==0.69.0 hassil==1.2.5 home-assistant-bluetooth==1.10.2 home-assistant-frontend==20230802.0 -home-assistant-intents==2023.7.25 +home-assistant-intents==2023.8.2 httpx==0.24.1 ifaddr==0.2.0 janus==1.0.0 diff --git a/requirements_all.txt b/requirements_all.txt index 2a2f0d1aa20..3191f722f18 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -991,7 +991,7 @@ holidays==0.28 home-assistant-frontend==20230802.0 # homeassistant.components.conversation -home-assistant-intents==2023.7.25 +home-assistant-intents==2023.8.2 # homeassistant.components.home_connect homeconnect==0.7.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index de45c832370..5b52309d58c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -777,7 +777,7 @@ holidays==0.28 home-assistant-frontend==20230802.0 # homeassistant.components.conversation -home-assistant-intents==2023.7.25 +home-assistant-intents==2023.8.2 # homeassistant.components.home_connect homeconnect==0.7.2 diff --git a/tests/components/conversation/snapshots/test_init.ambr b/tests/components/conversation/snapshots/test_init.ambr index f9fe284bcb0..f7145a9ab56 100644 --- a/tests/components/conversation/snapshots/test_init.ambr +++ b/tests/components/conversation/snapshots/test_init.ambr @@ -30,6 +30,7 @@ 'id': 'homeassistant', 'name': 'Home Assistant', 'supported_languages': list([ + 'af', 'ar', 'bg', 'bn', From d131b8c80b593042d8e23b565637abcc33c3aebc Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 2 Aug 2023 23:48:37 +0200 Subject: [PATCH 010/120] Add device naming to Yeelight (#97639) --- homeassistant/components/yeelight/light.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/yeelight/light.py b/homeassistant/components/yeelight/light.py index 35739b0f596..2180eecff22 100644 --- a/homeassistant/components/yeelight/light.py +++ b/homeassistant/components/yeelight/light.py @@ -930,6 +930,8 @@ class YeelightColorLightWithoutNightlightSwitch( ): """Representation of a Color Yeelight light.""" + _attr_name = None + class YeelightColorLightWithNightlightSwitch( YeelightNightLightSupport, YeelightColorLightSupport, YeelightGenericLight From 5da94f40ec63fea01c923882e2386c9b68da537f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 00:20:35 -1000 Subject: [PATCH 011/120] Fix typo in tplink OUI (#97644) The last two were reversed for https://ouilookup.com/search/788cb5 --- homeassistant/components/tplink/manifest.json | 2 +- homeassistant/generated/dhcp.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tplink/manifest.json b/homeassistant/components/tplink/manifest.json index c33106d13cc..b2fcc5c0161 100644 --- a/homeassistant/components/tplink/manifest.json +++ b/homeassistant/components/tplink/manifest.json @@ -154,7 +154,7 @@ }, { "hostname": "k[lps]*", - "macaddress": "788C5B*" + "macaddress": "788CB5*" } ], "documentation": "https://www.home-assistant.io/integrations/tplink", diff --git a/homeassistant/generated/dhcp.py b/homeassistant/generated/dhcp.py index 8b5dd91f64c..91a02ac3e06 100644 --- a/homeassistant/generated/dhcp.py +++ b/homeassistant/generated/dhcp.py @@ -782,7 +782,7 @@ DHCP: list[dict[str, str | bool]] = [ { "domain": "tplink", "hostname": "k[lps]*", - "macaddress": "788C5B*", + "macaddress": "788CB5*", }, { "domain": "tuya", From a36e746eb46270a46d5a263607096055784183e8 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 3 Aug 2023 09:13:23 +0200 Subject: [PATCH 012/120] Revert "Add device naming to Yeelight" (#97647) Revert "Add device naming to Yeelight (#97639)" This reverts commit 82f27115f5b53074fa385cd571c37115544efbe8. --- homeassistant/components/yeelight/light.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/yeelight/light.py b/homeassistant/components/yeelight/light.py index 2180eecff22..35739b0f596 100644 --- a/homeassistant/components/yeelight/light.py +++ b/homeassistant/components/yeelight/light.py @@ -930,8 +930,6 @@ class YeelightColorLightWithoutNightlightSwitch( ): """Representation of a Color Yeelight light.""" - _attr_name = None - class YeelightColorLightWithNightlightSwitch( YeelightNightLightSupport, YeelightColorLightSupport, YeelightGenericLight From 2f5f15b3452125182249223757ff49aff1fe781f Mon Sep 17 00:00:00 2001 From: Nick Iacullo Date: Thu, 3 Aug 2023 09:30:56 -0700 Subject: [PATCH 013/120] Enable the `PRESET_MODE` `FanEntityFeature` for VeSync air purifiers (#97657) --- homeassistant/components/vesync/fan.py | 4 ++-- .../vesync/snapshots/test_diagnostics.ambr | 2 +- tests/components/vesync/snapshots/test_fan.ambr | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/vesync/fan.py b/homeassistant/components/vesync/fan.py index a3bf027c28f..e5347b204e6 100644 --- a/homeassistant/components/vesync/fan.py +++ b/homeassistant/components/vesync/fan.py @@ -86,10 +86,10 @@ def _setup_entities(devices, async_add_entities): class VeSyncFanHA(VeSyncDevice, FanEntity): """Representation of a VeSync fan.""" - _attr_supported_features = FanEntityFeature.SET_SPEED + _attr_supported_features = FanEntityFeature.SET_SPEED | FanEntityFeature.PRESET_MODE _attr_name = None - def __init__(self, fan): + def __init__(self, fan) -> None: """Initialize the VeSync fan device.""" super().__init__(fan) self.smartfan = fan diff --git a/tests/components/vesync/snapshots/test_diagnostics.ambr b/tests/components/vesync/snapshots/test_diagnostics.ambr index c463db179eb..10dfdd2ba14 100644 --- a/tests/components/vesync/snapshots/test_diagnostics.ambr +++ b/tests/components/vesync/snapshots/test_diagnostics.ambr @@ -200,7 +200,7 @@ 'auto', 'sleep', ]), - 'supported_features': 1, + 'supported_features': 9, }), 'entity_id': 'fan.fan', 'last_changed': str, diff --git a/tests/components/vesync/snapshots/test_fan.ambr b/tests/components/vesync/snapshots/test_fan.ambr index 428f066e6cc..fa1a7a7b332 100644 --- a/tests/components/vesync/snapshots/test_fan.ambr +++ b/tests/components/vesync/snapshots/test_fan.ambr @@ -58,7 +58,7 @@ 'original_icon': None, 'original_name': None, 'platform': 'vesync', - 'supported_features': , + 'supported_features': , 'translation_key': None, 'unique_id': 'air-purifier', 'unit_of_measurement': None, @@ -73,7 +73,7 @@ 'auto', 'sleep', ]), - 'supported_features': , + 'supported_features': , }), 'context': , 'entity_id': 'fan.air_purifier_131s', @@ -140,7 +140,7 @@ 'original_icon': None, 'original_name': None, 'platform': 'vesync', - 'supported_features': , + 'supported_features': , 'translation_key': None, 'unique_id': 'asd_sdfKIHG7IJHGwJGJ7GJ_ag5h3G55', 'unit_of_measurement': None, @@ -161,7 +161,7 @@ 'sleep', ]), 'screen_status': True, - 'supported_features': , + 'supported_features': , }), 'context': , 'entity_id': 'fan.air_purifier_200s', @@ -229,7 +229,7 @@ 'original_icon': None, 'original_name': None, 'platform': 'vesync', - 'supported_features': , + 'supported_features': , 'translation_key': None, 'unique_id': '400s-purifier', 'unit_of_measurement': None, @@ -251,7 +251,7 @@ 'sleep', ]), 'screen_status': True, - 'supported_features': , + 'supported_features': , }), 'context': , 'entity_id': 'fan.air_purifier_400s', @@ -319,7 +319,7 @@ 'original_icon': None, 'original_name': None, 'platform': 'vesync', - 'supported_features': , + 'supported_features': , 'translation_key': None, 'unique_id': '600s-purifier', 'unit_of_measurement': None, @@ -341,7 +341,7 @@ 'sleep', ]), 'screen_status': True, - 'supported_features': , + 'supported_features': , }), 'context': , 'entity_id': 'fan.air_purifier_600s', From 6a8484b6daca3b91d8340dd418ebcd65abb8f4bf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 00:35:22 -1000 Subject: [PATCH 014/120] Fix tplink child plug state reporting (#97658) regressed in https://github.com/home-assistant/core/pull/96246 --- homeassistant/components/tplink/switch.py | 11 ++++-- tests/components/tplink/__init__.py | 2 + tests/components/tplink/test_switch.py | 45 +++++++++++++++-------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/tplink/switch.py b/homeassistant/components/tplink/switch.py index 6c843246663..fb812abc293 100644 --- a/homeassistant/components/tplink/switch.py +++ b/homeassistant/components/tplink/switch.py @@ -116,7 +116,7 @@ class SmartPlugSwitchChild(SmartPlugSwitch): coordinator: TPLinkDataUpdateCoordinator, plug: SmartDevice, ) -> None: - """Initialize the switch.""" + """Initialize the child switch.""" super().__init__(device, coordinator) self._plug = plug self._attr_unique_id = legacy_device_id(plug) @@ -124,10 +124,15 @@ class SmartPlugSwitchChild(SmartPlugSwitch): @async_refresh_after async def async_turn_on(self, **kwargs: Any) -> None: - """Turn the switch on.""" + """Turn the child switch on.""" await self._plug.turn_on() @async_refresh_after async def async_turn_off(self, **kwargs: Any) -> None: - """Turn the switch off.""" + """Turn the child switch off.""" await self._plug.turn_off() + + @property + def is_on(self) -> bool: + """Return true if child switch is on.""" + return bool(self._plug.is_on) diff --git a/tests/components/tplink/__init__.py b/tests/components/tplink/__init__.py index 4232d3e6909..816251ae3bb 100644 --- a/tests/components/tplink/__init__.py +++ b/tests/components/tplink/__init__.py @@ -180,12 +180,14 @@ def _mocked_strip() -> SmartStrip: plug0.alias = "Plug0" plug0.device_id = "bb:bb:cc:dd:ee:ff_PLUG0DEVICEID" plug0.mac = "bb:bb:cc:dd:ee:ff" + plug0.is_on = True plug0.protocol = _mock_protocol() plug1 = _mocked_plug() plug1.device_id = "cc:bb:cc:dd:ee:ff_PLUG1DEVICEID" plug1.mac = "cc:bb:cc:dd:ee:ff" plug1.alias = "Plug1" plug1.protocol = _mock_protocol() + plug1.is_on = False strip.children = [plug0, plug1] return strip diff --git a/tests/components/tplink/test_switch.py b/tests/components/tplink/test_switch.py index 1e5e03c0f37..05286e5ff48 100644 --- a/tests/components/tplink/test_switch.py +++ b/tests/components/tplink/test_switch.py @@ -9,7 +9,7 @@ import pytest from homeassistant.components import tplink from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.tplink.const import DOMAIN -from homeassistant.const import ATTR_ENTITY_ID, STATE_ON, STATE_UNAVAILABLE +from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON, STATE_UNAVAILABLE from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.setup import async_setup_component @@ -146,22 +146,37 @@ async def test_strip(hass: HomeAssistant) -> None: # since this is what the previous version did assert hass.states.get("switch.my_strip") is None - for plug_id in range(2): - entity_id = f"switch.my_strip_plug{plug_id}" - state = hass.states.get(entity_id) - assert state.state == STATE_ON + entity_id = "switch.my_strip_plug0" + state = hass.states.get(entity_id) + assert state.state == STATE_ON - await hass.services.async_call( - SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True - ) - strip.children[plug_id].turn_off.assert_called_once() - strip.children[plug_id].turn_off.reset_mock() + await hass.services.async_call( + SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + strip.children[0].turn_off.assert_called_once() + strip.children[0].turn_off.reset_mock() - await hass.services.async_call( - SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True - ) - strip.children[plug_id].turn_on.assert_called_once() - strip.children[plug_id].turn_on.reset_mock() + await hass.services.async_call( + SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + strip.children[0].turn_on.assert_called_once() + strip.children[0].turn_on.reset_mock() + + entity_id = "switch.my_strip_plug1" + state = hass.states.get(entity_id) + assert state.state == STATE_OFF + + await hass.services.async_call( + SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + strip.children[1].turn_off.assert_called_once() + strip.children[1].turn_off.reset_mock() + + await hass.services.async_call( + SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True + ) + strip.children[1].turn_on.assert_called_once() + strip.children[1].turn_on.reset_mock() async def test_strip_unique_ids(hass: HomeAssistant) -> None: From 79729043ed464a324185a867d428ee5df09d61d6 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Thu, 3 Aug 2023 13:59:37 +0200 Subject: [PATCH 015/120] Fix date and timestamp device class in Command Line Sensor (#97663) * Fix date in Command Line sensor * prettier --- .../components/command_line/sensor.py | 24 ++++++--- tests/components/command_line/test_sensor.py | 51 +++++++++++++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/command_line/sensor.py b/homeassistant/components/command_line/sensor.py index 1b865827e69..dd5ad2d5190 100644 --- a/homeassistant/components/command_line/sensor.py +++ b/homeassistant/components/command_line/sensor.py @@ -15,9 +15,11 @@ from homeassistant.components.sensor import ( DOMAIN as SENSOR_DOMAIN, PLATFORM_SCHEMA, STATE_CLASSES_SCHEMA, + SensorDeviceClass, SensorEntity, SensorStateClass, ) +from homeassistant.components.sensor.helpers import async_parse_date_datetime from homeassistant.const import ( CONF_COMMAND, CONF_DEVICE_CLASS, @@ -206,14 +208,24 @@ class CommandSensor(ManualTriggerEntity, SensorEntity): return if self._value_template is not None: - self._attr_native_value = ( - self._value_template.async_render_with_possible_json_value( - value, - None, - ) + value = self._value_template.async_render_with_possible_json_value( + value, + None, ) - else: + + if self.device_class not in { + SensorDeviceClass.DATE, + SensorDeviceClass.TIMESTAMP, + }: self._attr_native_value = value + self._process_manual_data(value) + return + + self._attr_native_value = None + if value is not None: + self._attr_native_value = async_parse_date_datetime( + value, self.entity_id, self.device_class + ) self._process_manual_data(value) self.async_write_ha_state() diff --git a/tests/components/command_line/test_sensor.py b/tests/components/command_line/test_sensor.py index a0f8f2cdf84..bc24ff5419f 100644 --- a/tests/components/command_line/test_sensor.py +++ b/tests/components/command_line/test_sensor.py @@ -646,3 +646,54 @@ async def test_updating_manually( ) await hass.async_block_till_done() assert called + + +@pytest.mark.parametrize( + "get_config", + [ + { + "command_line": [ + { + "sensor": { + "name": "Test", + "command": "echo 2022-12-22T13:15:30Z", + "device_class": "timestamp", + } + } + ] + } + ], +) +async def test_scrape_sensor_device_timestamp( + hass: HomeAssistant, load_yaml_integration: None +) -> None: + """Test Command Line sensor with a device of type TIMESTAMP.""" + entity_state = hass.states.get("sensor.test") + assert entity_state + assert entity_state.state == "2022-12-22T13:15:30+00:00" + + +@pytest.mark.parametrize( + "get_config", + [ + { + "command_line": [ + { + "sensor": { + "name": "Test", + "command": "echo January 17, 2022", + "device_class": "date", + "value_template": "{{ strptime(value, '%B %d, %Y').strftime('%Y-%m-%d') }}", + } + } + ] + } + ], +) +async def test_scrape_sensor_device_date( + hass: HomeAssistant, load_yaml_integration: None +) -> None: + """Test Command Line sensor with a device of type DATE.""" + entity_state = hass.states.get("sensor.test") + assert entity_state + assert entity_state.state == "2022-01-17" From 1945275b7c1fbee53b333014f61287082938dca1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 06:57:34 -1000 Subject: [PATCH 016/120] Bump zeroconf to 0.72.3 (#97668) --- homeassistant/components/zeroconf/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/zeroconf/manifest.json b/homeassistant/components/zeroconf/manifest.json index 73ebe15d0c7..bb0ec29271e 100644 --- a/homeassistant/components/zeroconf/manifest.json +++ b/homeassistant/components/zeroconf/manifest.json @@ -8,5 +8,5 @@ "iot_class": "local_push", "loggers": ["zeroconf"], "quality_scale": "internal", - "requirements": ["zeroconf==0.72.0"] + "requirements": ["zeroconf==0.72.3"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 6564dfb3a0d..12e8afc3cf7 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -52,7 +52,7 @@ voluptuous-serialize==2.6.0 voluptuous==0.13.1 webrtcvad==2.0.10 yarl==1.9.2 -zeroconf==0.72.0 +zeroconf==0.72.3 # Constrain pycryptodome to avoid vulnerability # see https://github.com/home-assistant/core/pull/16238 diff --git a/requirements_all.txt b/requirements_all.txt index 3191f722f18..bd803d8152d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2749,7 +2749,7 @@ zamg==0.2.4 zengge==0.2 # homeassistant.components.zeroconf -zeroconf==0.72.0 +zeroconf==0.72.3 # homeassistant.components.zeversolar zeversolar==0.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5b52309d58c..fe022d74c6b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2022,7 +2022,7 @@ youtubeaio==1.1.5 zamg==0.2.4 # homeassistant.components.zeroconf -zeroconf==0.72.0 +zeroconf==0.72.3 # homeassistant.components.zeversolar zeversolar==0.3.1 From 0a24299e231a335e5e03d184ec6fa1aea24f363f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 01:31:49 -1000 Subject: [PATCH 017/120] Bump pyatv to 0.13.3 (#97670) changelog: https://github.com/postlund/pyatv/compare/v0.13.2...v0.13.3 maybe fixes #80215 --- homeassistant/components/apple_tv/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/apple_tv/manifest.json b/homeassistant/components/apple_tv/manifest.json index 4ead41e86e9..1d1c26b5fcd 100644 --- a/homeassistant/components/apple_tv/manifest.json +++ b/homeassistant/components/apple_tv/manifest.json @@ -7,7 +7,7 @@ "documentation": "https://www.home-assistant.io/integrations/apple_tv", "iot_class": "local_push", "loggers": ["pyatv", "srptools"], - "requirements": ["pyatv==0.13.2"], + "requirements": ["pyatv==0.13.3"], "zeroconf": [ "_mediaremotetv._tcp.local.", "_companion-link._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index bd803d8152d..67041b69fa0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1572,7 +1572,7 @@ pyatag==0.3.5.3 pyatmo==7.5.0 # homeassistant.components.apple_tv -pyatv==0.13.2 +pyatv==0.13.3 # homeassistant.components.aussie_broadband pyaussiebb==0.0.15 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fe022d74c6b..38022121f85 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1178,7 +1178,7 @@ pyatag==0.3.5.3 pyatmo==7.5.0 # homeassistant.components.apple_tv -pyatv==0.13.2 +pyatv==0.13.3 # homeassistant.components.aussie_broadband pyaussiebb==0.0.15 From 12d3bce3a73189a57b214b969c9e867c50d646ab Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Thu, 3 Aug 2023 21:06:45 +0200 Subject: [PATCH 018/120] Fix color mode attribute for both official and non official Hue lights (#97683) --- homeassistant/components/hue/v2/light.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/hue/v2/light.py b/homeassistant/components/hue/v2/light.py index 957aa4a7806..f42da406599 100644 --- a/homeassistant/components/hue/v2/light.py +++ b/homeassistant/components/hue/v2/light.py @@ -89,6 +89,7 @@ class HueLight(HueBaseEntity, LightEntity): self._supported_color_modes.add(ColorMode.BRIGHTNESS) # support transition if brightness control self._attr_supported_features |= LightEntityFeature.TRANSITION + self._color_temp_active: bool = False # get list of supported effects (combine effects and timed_effects) self._attr_effect_list = [] if effects := resource.effects: @@ -121,10 +122,8 @@ class HueLight(HueBaseEntity, LightEntity): @property def color_mode(self) -> ColorMode: """Return the color mode of the light.""" - if color_temp := self.resource.color_temperature: - # Hue lights return `mired_valid` to indicate CT is active - if color_temp.mirek is not None: - return ColorMode.COLOR_TEMP + if self.color_temp_active: + return ColorMode.COLOR_TEMP if self.resource.supports_color: return ColorMode.XY if self.resource.supports_dimming: @@ -132,6 +131,18 @@ class HueLight(HueBaseEntity, LightEntity): # fallback to on_off return ColorMode.ONOFF + @property + def color_temp_active(self) -> bool: + """Return if the light is in Color Temperature mode.""" + color_temp = self.resource.color_temperature + if color_temp is None or color_temp.mirek is None: + return False + # Official Hue lights return `mirek_valid` to indicate CT is active + # while non-official lights do not. + if self.device.product_data.certified: + return self.resource.color_temperature.mirek_valid + return self._color_temp_active + @property def xy_color(self) -> tuple[float, float] | None: """Return the xy color.""" @@ -193,6 +204,7 @@ class HueLight(HueBaseEntity, LightEntity): xy_color = kwargs.get(ATTR_XY_COLOR) color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP)) brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS)) + self._color_temp_active = color_temp is not None flash = kwargs.get(ATTR_FLASH) effect = effect_str = kwargs.get(ATTR_EFFECT) if effect_str in (EFFECT_NONE, EFFECT_NONE.lower()): From 694d28ae3bb52015a5fa6059b9a90bcfe9727ce1 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Thu, 3 Aug 2023 21:11:15 +0200 Subject: [PATCH 019/120] Fix UniFi image platform not loading when passphrase is missing from WLAN (#97684) --- homeassistant/components/unifi/image.py | 4 ++-- homeassistant/components/unifi/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/unifi/image.py b/homeassistant/components/unifi/image.py index dc4fb93eded..c3969c21bc4 100644 --- a/homeassistant/components/unifi/image.py +++ b/homeassistant/components/unifi/image.py @@ -41,7 +41,7 @@ class UnifiImageEntityDescriptionMixin(Generic[HandlerT, ApiItemT]): """Validate and load entities from different UniFi handlers.""" image_fn: Callable[[UniFiController, ApiItemT], bytes] - value_fn: Callable[[ApiItemT], str] + value_fn: Callable[[ApiItemT], str | None] @dataclass @@ -99,7 +99,7 @@ class UnifiImageEntity(UnifiEntity[HandlerT, ApiItemT], ImageEntity): _attr_content_type = "image/png" current_image: bytes | None = None - previous_value = "" + previous_value: str | None = None def __init__( self, diff --git a/homeassistant/components/unifi/manifest.json b/homeassistant/components/unifi/manifest.json index c34d1035158..4cc45ddb6b8 100644 --- a/homeassistant/components/unifi/manifest.json +++ b/homeassistant/components/unifi/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_push", "loggers": ["aiounifi"], "quality_scale": "platinum", - "requirements": ["aiounifi==50"], + "requirements": ["aiounifi==51"], "ssdp": [ { "manufacturer": "Ubiquiti Networks", diff --git a/requirements_all.txt b/requirements_all.txt index 67041b69fa0..250d1a452ef 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -360,7 +360,7 @@ aiosyncthing==0.5.1 aiotractive==0.5.5 # homeassistant.components.unifi -aiounifi==50 +aiounifi==51 # homeassistant.components.vlc_telnet aiovlc==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 38022121f85..2b5e7ea5658 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -335,7 +335,7 @@ aiosyncthing==0.5.1 aiotractive==0.5.5 # homeassistant.components.unifi -aiounifi==50 +aiounifi==51 # homeassistant.components.vlc_telnet aiovlc==0.1.0 From 7a244e30a4fd9e4999e5913de2393cd33fdec656 Mon Sep 17 00:00:00 2001 From: Nerdix <70015952+N3rdix@users.noreply.github.com> Date: Fri, 4 Aug 2023 11:31:54 +0200 Subject: [PATCH 020/120] Fix Kostal_Plenticore SELECT entities using device_info correctly (#97690) --- homeassistant/components/kostal_plenticore/select.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/kostal_plenticore/select.py b/homeassistant/components/kostal_plenticore/select.py index 2118d4b47c6..1a89e5617cc 100644 --- a/homeassistant/components/kostal_plenticore/select.py +++ b/homeassistant/components/kostal_plenticore/select.py @@ -111,7 +111,7 @@ class PlenticoreDataSelect( self.platform_name = platform_name self.module_id = description.module_id self.data_id = description.key - self._device_info = device_info + self._attr_device_info = device_info self._attr_unique_id = f"{entry_id}_{description.module_id}" @property From 0617363f53551fc33b41d6e4565b16d28a22aa7d Mon Sep 17 00:00:00 2001 From: Cyr-ius <1258123+cyr-ius@users.noreply.github.com> Date: Fri, 4 Aug 2023 09:25:51 +0200 Subject: [PATCH 021/120] Fix freebox enumerate raid disks (#97696) --- homeassistant/components/freebox/router.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index 4a9c22847ae..122242f1959 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -161,10 +161,13 @@ class FreeboxRouter: async def _update_raids_sensors(self) -> None: """Update Freebox raids.""" # None at first request - fbx_raids: list[dict[str, Any]] = await self._api.storage.get_raids() or [] - - for fbx_raid in fbx_raids: - self.raids[fbx_raid["id"]] = fbx_raid + try: + fbx_raids: list[dict[str, Any]] = await self._api.storage.get_raids() or [] + except HttpRequestError: + _LOGGER.warning("Unable to enumerate raid disks") + else: + for fbx_raid in fbx_raids: + self.raids[fbx_raid["id"]] = fbx_raid async def update_home_devices(self) -> None: """Update Home devices (alarm, light, sensor, switch, remote ...).""" From f066b4645a26575a87ee5e4a89d852909cf11d73 Mon Sep 17 00:00:00 2001 From: amitfin Date: Fri, 4 Aug 2023 13:51:04 +0300 Subject: [PATCH 022/120] Fix allow_name_translation logic (#97701) --- script/hassfest/translations.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/script/hassfest/translations.py b/script/hassfest/translations.py index 1754c166ef7..22c3e927703 100644 --- a/script/hassfest/translations.py +++ b/script/hassfest/translations.py @@ -61,8 +61,9 @@ def allow_name_translation(integration: Integration) -> bool: """Validate that the translation name is not the same as the integration name.""" # Only enforce for core because custom integrations can't be # added to allow list. - return integration.core and ( - integration.domain in ALLOW_NAME_TRANSLATION + return ( + not integration.core + or integration.domain in ALLOW_NAME_TRANSLATION or integration.quality_scale == "internal" ) From 6a9318b90ae8a6dc42baaa97c41b6381eb32ae50 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:15:08 -0700 Subject: [PATCH 023/120] Fix NWS twice_daily forecast day/night detection (#97703) --- homeassistant/components/nws/const.py | 1 - homeassistant/components/nws/weather.py | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/nws/const.py b/homeassistant/components/nws/const.py index 109af7a565b..e5718d5132f 100644 --- a/homeassistant/components/nws/const.py +++ b/homeassistant/components/nws/const.py @@ -26,7 +26,6 @@ CONF_STATION = "station" ATTRIBUTION = "Data from National Weather Service/NOAA" ATTR_FORECAST_DETAILED_DESCRIPTION = "detailed_description" -ATTR_FORECAST_DAYTIME = "daytime" CONDITION_CLASSES: dict[str, list[str]] = { ATTR_CONDITION_EXCEPTIONAL: [ diff --git a/homeassistant/components/nws/weather.py b/homeassistant/components/nws/weather.py index e8a35ba66f1..8ddf842cd62 100644 --- a/homeassistant/components/nws/weather.py +++ b/homeassistant/components/nws/weather.py @@ -9,6 +9,7 @@ from homeassistant.components.weather import ( ATTR_CONDITION_SUNNY, ATTR_FORECAST_CONDITION, ATTR_FORECAST_HUMIDITY, + ATTR_FORECAST_IS_DAYTIME, ATTR_FORECAST_NATIVE_DEW_POINT, ATTR_FORECAST_NATIVE_TEMP, ATTR_FORECAST_NATIVE_WIND_SPEED, @@ -36,7 +37,6 @@ from homeassistant.util.unit_system import UnitSystem from . import base_unique_id, device_info from .const import ( - ATTR_FORECAST_DAYTIME, ATTR_FORECAST_DETAILED_DESCRIPTION, ATTRIBUTION, CONDITION_CLASSES, @@ -101,7 +101,6 @@ if TYPE_CHECKING: """Forecast with extra fields needed for NWS.""" detailed_description: str | None - daytime: bool | None class NWSWeather(WeatherEntity): @@ -268,7 +267,7 @@ class NWSWeather(WeatherEntity): data[ATTR_FORECAST_HUMIDITY] = forecast_entry.get("relativeHumidity") if self.mode == DAYNIGHT: - data[ATTR_FORECAST_DAYTIME] = forecast_entry.get("isDaytime") + data[ATTR_FORECAST_IS_DAYTIME] = forecast_entry.get("isDaytime") time = forecast_entry.get("iconTime") weather = forecast_entry.get("iconWeather") From 16e1212572aec41758c4f3514ea007f914fc0115 Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 3 Aug 2023 11:07:44 -0700 Subject: [PATCH 024/120] Bump opower to 0.0.19 (#97706) --- 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 c0eb319c10c..1b351d73011 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.18"] + "requirements": ["opower==0.0.19"] } diff --git a/requirements_all.txt b/requirements_all.txt index 250d1a452ef..3526ad77311 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.18 +opower==0.0.19 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2b5e7ea5658..655162059ef 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.18 +opower==0.0.19 # homeassistant.components.oralb oralb-ble==0.17.6 From 047a210786aa484d8dae5a47e35ac97c8ae34600 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:36:09 +0200 Subject: [PATCH 025/120] Fix detection of client wan-access rule in AVM Fritz!Box Tools (#97708) --- homeassistant/components/fritz/common.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index cdea8ebee54..8dfe5be9308 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -469,6 +469,11 @@ class FritzBoxTools( if not host.get("MACAddress"): continue + if (wan_access := host.get("X_AVM-DE_WANAccess")) is not None: + wan_access_result = "granted" in wan_access + else: + wan_access_result = None + hosts[host["MACAddress"]] = Device( name=host["HostName"], connected=host["Active"], @@ -476,7 +481,7 @@ class FritzBoxTools( connection_type="", ip_address=host["IPAddress"], ssid=None, - wan_access="granted" in host["X_AVM-DE_WANAccess"], + wan_access=wan_access_result, ) if not self.fritz_status.device_has_mesh_support or ( From 2b876fa4851946c47bdb21468d9bc8731a7d9e8f Mon Sep 17 00:00:00 2001 From: Matthias Alphart Date: Thu, 3 Aug 2023 23:23:12 +0200 Subject: [PATCH 026/120] Fix unloading KNX integration without sensors (#97720) --- homeassistant/components/knx/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/knx/__init__.py b/homeassistant/components/knx/__init__.py index 1bb6d9bbdd2..3444e9b002a 100644 --- a/homeassistant/components/knx/__init__.py +++ b/homeassistant/components/knx/__init__.py @@ -342,10 +342,13 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: unload_ok = await hass.config_entries.async_unload_platforms( entry, [ - platform - for platform in SUPPORTED_PLATFORMS - if platform in hass.data[DATA_KNX_CONFIG] - and platform is not Platform.NOTIFY + Platform.SENSOR, # always unload system entities (telegram counter, etc.) + *[ + platform + for platform in SUPPORTED_PLATFORMS + if platform in hass.data[DATA_KNX_CONFIG] + and platform not in (Platform.SENSOR, Platform.NOTIFY) + ], ], ) if unload_ok: From 5283afc1168c9c5ea1863c4a6c4e0944c071d9bd Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sun, 30 Jul 2023 15:30:13 +0200 Subject: [PATCH 027/120] Update zigpy to 0.56.3 (#97480) --- homeassistant/components/zha/manifest.json | 4 ++-- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 5e33377ec0e..5d0fdc646cf 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -25,10 +25,10 @@ "pyserial-asyncio==0.6", "zha-quirks==0.0.102", "zigpy-deconz==0.21.0", - "zigpy==0.56.2", + "zigpy==0.56.3", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", - "zigpy-znp==0.11.3" + "zigpy-znp==0.11.4" ], "usb": [ { diff --git a/requirements_all.txt b/requirements_all.txt index 3526ad77311..ae45bb029a5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2773,10 +2773,10 @@ zigpy-xbee==0.18.1 zigpy-zigate==0.11.0 # homeassistant.components.zha -zigpy-znp==0.11.3 +zigpy-znp==0.11.4 # homeassistant.components.zha -zigpy==0.56.2 +zigpy==0.56.3 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 655162059ef..38a3f6d09fa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2040,10 +2040,10 @@ zigpy-xbee==0.18.1 zigpy-zigate==0.11.0 # homeassistant.components.zha -zigpy-znp==0.11.3 +zigpy-znp==0.11.4 # homeassistant.components.zha -zigpy==0.56.2 +zigpy==0.56.3 # homeassistant.components.zwave_js zwave-js-server-python==0.49.0 From 79486f18809ab960f83ab7af44492a088d731b9b Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Fri, 4 Aug 2023 00:11:36 +0200 Subject: [PATCH 028/120] Bump zigpy to 0.56.4 (#97722) --- homeassistant/components/zha/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 5d0fdc646cf..041a93a8ead 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -25,7 +25,7 @@ "pyserial-asyncio==0.6", "zha-quirks==0.0.102", "zigpy-deconz==0.21.0", - "zigpy==0.56.3", + "zigpy==0.56.4", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.4" diff --git a/requirements_all.txt b/requirements_all.txt index ae45bb029a5..e8520806328 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2776,7 +2776,7 @@ zigpy-zigate==0.11.0 zigpy-znp==0.11.4 # homeassistant.components.zha -zigpy==0.56.3 +zigpy==0.56.4 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 38a3f6d09fa..c79da53ec2c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2043,7 +2043,7 @@ zigpy-zigate==0.11.0 zigpy-znp==0.11.4 # homeassistant.components.zha -zigpy==0.56.3 +zigpy==0.56.4 # homeassistant.components.zwave_js zwave-js-server-python==0.49.0 From 53ee17854501bda202582b12442579506232a443 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Fri, 4 Aug 2023 09:34:04 +0200 Subject: [PATCH 029/120] Fix keymitt_ble RuntimeWarning (#97729) --- homeassistant/components/keymitt_ble/config_flow.py | 2 +- tests/components/keymitt_ble/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/keymitt_ble/config_flow.py b/homeassistant/components/keymitt_ble/config_flow.py index 49ab04163dc..e8176b152a6 100644 --- a/homeassistant/components/keymitt_ble/config_flow.py +++ b/homeassistant/components/keymitt_ble/config_flow.py @@ -138,7 +138,7 @@ class MicroBotConfigFlow(ConfigFlow, domain=DOMAIN): await self._client.connect(init=True) return self.async_show_form(step_id="link") - if not self._client.is_connected(): + if not await self._client.is_connected(): errors["base"] = "linking" else: await self._client.disconnect() diff --git a/tests/components/keymitt_ble/__init__.py b/tests/components/keymitt_ble/__init__.py index 2938e22c924..c6e56739d76 100644 --- a/tests/components/keymitt_ble/__init__.py +++ b/tests/components/keymitt_ble/__init__.py @@ -77,6 +77,6 @@ class MockMicroBotApiClientFail: async def disconnect(self): """Mock disconnect.""" - def is_connected(self): + async def is_connected(self): """Mock disconnected.""" return False From 9bec7ea93ba3aa050db29b0fb2b94dbdb3f14356 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 16:48:53 -1000 Subject: [PATCH 030/120] Bump zeroconf to 0.74.0 (#97745) * Bump zeroconf to 0.74.0 changelog: https://github.com/python-zeroconf/python-zeroconf/compare/0.72.3...0.74.0 - more cython build fixes - performance improvements (mostly for pyatv) * handle typing * handle typing * remove if TYPE_CHECKING, this doesnt get called that often * remove if TYPE_CHECKING, this doesnt get called that often --- homeassistant/components/thread/discovery.py | 33 +++++++++++++------ homeassistant/components/zeroconf/__init__.py | 8 ++++- .../components/zeroconf/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/thread/discovery.py b/homeassistant/components/thread/discovery.py index 1006a44d5d3..d07469f36fb 100644 --- a/homeassistant/components/thread/discovery.py +++ b/homeassistant/components/thread/discovery.py @@ -57,25 +57,29 @@ def async_discovery_data_from_service( except UnicodeDecodeError: return None - ext_addr = service.properties.get(b"xa") - ext_pan_id = service.properties.get(b"xp") - network_name = try_decode(service.properties.get(b"nn")) - model_name = try_decode(service.properties.get(b"mn")) + # Service properties are always bytes if they are set from the network. + # For legacy backwards compatibility zeroconf allows properties to be set + # as strings but we never do that so we can safely cast here. + service_properties = cast(dict[bytes, bytes | None], service.properties) + ext_addr = service_properties.get(b"xa") + ext_pan_id = service_properties.get(b"xp") + network_name = try_decode(service_properties.get(b"nn")) + model_name = try_decode(service_properties.get(b"mn")) server = service.server - vendor_name = try_decode(service.properties.get(b"vn")) - thread_version = try_decode(service.properties.get(b"tv")) + vendor_name = try_decode(service_properties.get(b"vn")) + thread_version = try_decode(service_properties.get(b"tv")) unconfigured = None brand = KNOWN_BRANDS.get(vendor_name) if brand == "homeassistant": # Attempt to detect incomplete configuration - if (state_bitmap_b := service.properties.get(b"sb")) is not None: + if (state_bitmap_b := service_properties.get(b"sb")) is not None: try: state_bitmap = StateBitmap.from_bytes(state_bitmap_b) if not state_bitmap.is_active: unconfigured = True except ValueError: _LOGGER.debug("Failed to decode state bitmap in service %s", service) - if service.properties.get(b"at") is None: + if service_properties.get(b"at") is None: unconfigured = True return ThreadRouterDiscoveryData( @@ -168,10 +172,19 @@ class ThreadRouterDiscovery: return _LOGGER.debug("_add_update_service %s %s", name, service) + # Service properties are always bytes if they are set from the network. + # For legacy backwards compatibility zeroconf allows properties to be set + # as strings but we never do that so we can safely cast here. + service_properties = cast(dict[bytes, bytes | None], service.properties) + + if not (xa := service_properties.get(b"xa")): + _LOGGER.debug("_add_update_service failed to find xa in %s", service) + return + # We use the extended mac address as key, bail out if it's missing try: - extended_mac_address = service.properties[b"xa"].hex() - except (KeyError, UnicodeDecodeError) as err: + extended_mac_address = xa.hex() + except UnicodeDecodeError as err: _LOGGER.debug("_add_update_service failed to parse service %s", err) return diff --git a/homeassistant/components/zeroconf/__init__.py b/homeassistant/components/zeroconf/__init__.py index f77909b1bdd..b85f9f0fd83 100644 --- a/homeassistant/components/zeroconf/__init__.py +++ b/homeassistant/components/zeroconf/__init__.py @@ -553,11 +553,17 @@ def info_from_service(service: AsyncServiceInfo) -> ZeroconfServiceInfo | None: break if not host: return None + + # Service properties are always bytes if they are set from the network. + # For legacy backwards compatibility zeroconf allows properties to be set + # as strings but we never do that so we can safely cast here. + service_properties = cast(dict[bytes, bytes | None], service.properties) + properties: dict[str, Any] = { k.decode("ascii", "replace"): None if v is None else v.decode("utf-8", "replace") - for k, v in service.properties.items() + for k, v in service_properties.items() } assert service.server is not None, "server cannot be none if there are addresses" diff --git a/homeassistant/components/zeroconf/manifest.json b/homeassistant/components/zeroconf/manifest.json index bb0ec29271e..cd7b9e95e75 100644 --- a/homeassistant/components/zeroconf/manifest.json +++ b/homeassistant/components/zeroconf/manifest.json @@ -8,5 +8,5 @@ "iot_class": "local_push", "loggers": ["zeroconf"], "quality_scale": "internal", - "requirements": ["zeroconf==0.72.3"] + "requirements": ["zeroconf==0.74.0"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 12e8afc3cf7..fa5b52478d0 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -52,7 +52,7 @@ voluptuous-serialize==2.6.0 voluptuous==0.13.1 webrtcvad==2.0.10 yarl==1.9.2 -zeroconf==0.72.3 +zeroconf==0.74.0 # Constrain pycryptodome to avoid vulnerability # see https://github.com/home-assistant/core/pull/16238 diff --git a/requirements_all.txt b/requirements_all.txt index e8520806328..98d6c3f29db 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2749,7 +2749,7 @@ zamg==0.2.4 zengge==0.2 # homeassistant.components.zeroconf -zeroconf==0.72.3 +zeroconf==0.74.0 # homeassistant.components.zeversolar zeversolar==0.3.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c79da53ec2c..6a32c356d58 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2022,7 +2022,7 @@ youtubeaio==1.1.5 zamg==0.2.4 # homeassistant.components.zeroconf -zeroconf==0.72.3 +zeroconf==0.74.0 # homeassistant.components.zeversolar zeversolar==0.3.1 From cdabf76d158145bc0a34cb83263925d774b3331d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 3 Aug 2023 23:46:19 -1000 Subject: [PATCH 031/120] Avoid calling the http access logging when logging is disabled in emulated_hue (#97750) --- homeassistant/components/emulated_hue/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/emulated_hue/__init__.py b/homeassistant/components/emulated_hue/__init__.py index 1ba93da716c..a98d2c08a48 100644 --- a/homeassistant/components/emulated_hue/__init__.py +++ b/homeassistant/components/emulated_hue/__init__.py @@ -6,6 +6,7 @@ import logging from aiohttp import web import voluptuous as vol +from homeassistant.components.http import HomeAssistantAccessLogger from homeassistant.components.network import async_get_source_ip from homeassistant.const import ( CONF_ENTITIES, @@ -100,7 +101,7 @@ async def start_emulated_hue_bridge( config.advertise_port or config.listen_port, ) - runner = web.AppRunner(app) + runner = web.AppRunner(app, access_log_class=HomeAssistantAccessLogger) await runner.setup() site = web.TCPSite(runner, config.host_ip_addr, config.listen_port) From 39fc557189418ddce003f869e21b7af91dd288c4 Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 4 Aug 2023 00:32:59 -0700 Subject: [PATCH 032/120] Bump opower to 0.0.20 (#97752) --- 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 1b351d73011..94758720722 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.19"] + "requirements": ["opower==0.0.20"] } diff --git a/requirements_all.txt b/requirements_all.txt index 98d6c3f29db..a2c9bc85eb6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.19 +opower==0.0.20 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6a32c356d58..d35544c68d9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.19 +opower==0.0.20 # homeassistant.components.oralb oralb-ble==0.17.6 From 9479a59a2fbfa20f6ba70cce5ac1b3f3d4be3419 Mon Sep 17 00:00:00 2001 From: Maikel Punie Date: Fri, 4 Aug 2023 11:33:03 +0200 Subject: [PATCH 033/120] Bump pyduotecno to 2023.8.3 (#97759) --- 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 c0bd29547c5..69490b6b5aa 100644 --- a/homeassistant/components/duotecno/manifest.json +++ b/homeassistant/components/duotecno/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/duotecno", "iot_class": "local_push", - "requirements": ["pyduotecno==2023.8.1"] + "requirements": ["pyduotecno==2023.8.3"] } diff --git a/requirements_all.txt b/requirements_all.txt index a2c9bc85eb6..21d10628ecb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1650,7 +1650,7 @@ pydrawise==2023.7.1 pydroid-ipcam==2.0.0 # homeassistant.components.duotecno -pyduotecno==2023.8.1 +pyduotecno==2023.8.3 # homeassistant.components.ebox pyebox==1.1.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d35544c68d9..5cb970c7132 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1223,7 +1223,7 @@ pydiscovergy==2.0.1 pydroid-ipcam==2.0.0 # homeassistant.components.duotecno -pyduotecno==2023.8.1 +pyduotecno==2023.8.3 # homeassistant.components.econet pyeconet==0.1.20 From d71f16c8b12a1a1308ca6775aa336ef48ae49be2 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 4 Aug 2023 12:46:53 +0200 Subject: [PATCH 034/120] Add has entity name to Solarlog (#97764) --- homeassistant/components/solarlog/sensor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/solarlog/sensor.py b/homeassistant/components/solarlog/sensor.py index a69d2a4c382..936dc998c86 100644 --- a/homeassistant/components/solarlog/sensor.py +++ b/homeassistant/components/solarlog/sensor.py @@ -218,6 +218,8 @@ async def async_setup_entry( class SolarlogSensor(CoordinatorEntity[SolarlogData], SensorEntity): """Representation of a Sensor.""" + _attr_has_entity_name = True + entity_description: SolarLogSensorEntityDescription def __init__( @@ -228,7 +230,6 @@ class SolarlogSensor(CoordinatorEntity[SolarlogData], SensorEntity): """Initialize the sensor.""" super().__init__(coordinator) self.entity_description = description - self._attr_name = f"{coordinator.name} {description.name}" self._attr_unique_id = f"{coordinator.unique_id}_{description.key}" self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, coordinator.unique_id)}, From 3b48c8a0f5347af2ed54ab19cee7ea6511b08d28 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 4 Aug 2023 12:46:23 +0200 Subject: [PATCH 035/120] Fix WAQI being zero (#97767) --- homeassistant/components/waqi/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/waqi/sensor.py b/homeassistant/components/waqi/sensor.py index ae4e46c2a0b..71ec703df3f 100644 --- a/homeassistant/components/waqi/sensor.py +++ b/homeassistant/components/waqi/sensor.py @@ -142,7 +142,7 @@ class WaqiSensor(SensorEntity): @property def native_value(self): """Return the state of the device.""" - if value := self._data.get("aqi"): + if (value := self._data.get("aqi")) is not None: with suppress(ValueError): return float(value) return None From b00fc9660b4a2d6595e2c14f6f1d3fa634a293b9 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 4 Aug 2023 13:26:05 +0200 Subject: [PATCH 036/120] Bumped version to 2023.8.1 --- 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 db7ef9e305a..0568650deb5 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "0" +PATCH_VERSION: Final = "1" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index e4e8fab4b15..fdcd2788b58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.8.0" +version = "2023.8.1" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From a397782ae3f42d8063d52f2de934b7a6bce096da Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Fri, 4 Aug 2023 05:08:49 -0700 Subject: [PATCH 037/120] Handle Alert exception on notification failure (#93632) --- homeassistant/components/alert/__init__.py | 13 ++++++++++--- tests/components/alert/test_init.py | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/alert/__init__.py b/homeassistant/components/alert/__init__.py index 9b3fb0f29c8..721ed0d0c21 100644 --- a/homeassistant/components/alert/__init__.py +++ b/homeassistant/components/alert/__init__.py @@ -26,6 +26,7 @@ from homeassistant.const import ( STATE_ON, ) from homeassistant.core import HassJob, HomeAssistant +from homeassistant.exceptions import ServiceNotFound import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent @@ -293,9 +294,15 @@ class Alert(Entity): LOGGER.debug(msg_payload) for target in self._notifiers: - await self.hass.services.async_call( - DOMAIN_NOTIFY, target, msg_payload, context=self._context - ) + try: + await self.hass.services.async_call( + DOMAIN_NOTIFY, target, msg_payload, context=self._context + ) + except ServiceNotFound: + LOGGER.error( + "Failed to call notify.%s, retrying at next notification interval", + target, + ) async def async_turn_on(self, **kwargs: Any) -> None: """Async Unacknowledge alert.""" diff --git a/tests/components/alert/test_init.py b/tests/components/alert/test_init.py index 550727a2a22..8dfbb437646 100644 --- a/tests/components/alert/test_init.py +++ b/tests/components/alert/test_init.py @@ -36,6 +36,7 @@ from tests.common import async_mock_service NAME = "alert_test" DONE_MESSAGE = "alert_gone" NOTIFIER = "test" +BAD_NOTIFIER = "bad_notifier" TEMPLATE = "{{ states.sensor.test.entity_id }}" TEST_ENTITY = "sensor.test" TITLE = "{{ states.sensor.test.entity_id }}" @@ -199,6 +200,26 @@ async def test_notification( assert len(mock_notifier) == 2 +async def test_bad_notifier( + hass: HomeAssistant, mock_notifier: list[ServiceCall] +) -> None: + """Test a broken notifier does not break the alert.""" + config = deepcopy(TEST_CONFIG) + config[DOMAIN][NAME][CONF_NOTIFIERS] = [BAD_NOTIFIER, NOTIFIER] + assert await async_setup_component(hass, DOMAIN, config) + assert len(mock_notifier) == 0 + + hass.states.async_set("sensor.test", STATE_ON) + await hass.async_block_till_done() + assert len(mock_notifier) == 1 + assert hass.states.get(ENTITY_ID).state == STATE_ON + + hass.states.async_set("sensor.test", STATE_OFF) + await hass.async_block_till_done() + assert len(mock_notifier) == 2 + assert hass.states.get(ENTITY_ID).state == STATE_IDLE + + async def test_no_notifiers( hass: HomeAssistant, mock_notifier: list[ServiceCall] ) -> None: From 2e98c3f077e5e24aac57e228ae48ba97cb34a0a8 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sat, 5 Aug 2023 22:36:45 +0200 Subject: [PATCH 038/120] Add yeelight class to fix superclass issue (#97649) * Add device naming to Yeelight * Add extra light entity to fix superclass * Add extra light entity to fix superclass --- homeassistant/components/yeelight/light.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/yeelight/light.py b/homeassistant/components/yeelight/light.py index 35739b0f596..f5f39e9997d 100644 --- a/homeassistant/components/yeelight/light.py +++ b/homeassistant/components/yeelight/light.py @@ -297,7 +297,7 @@ async def async_setup_entry( _lights_setup_helper(YeelightColorLightWithNightlightSwitch) _lights_setup_helper(YeelightNightLightModeWithoutBrightnessControl) else: - _lights_setup_helper(YeelightColorLightWithoutNightlightSwitch) + _lights_setup_helper(YeelightColorLightWithoutNightlightSwitchLight) elif device_type == BulbType.WhiteTemp: if nl_switch_light and device.is_nightlight_supported: _lights_setup_helper(YeelightWithNightLight) @@ -931,6 +931,14 @@ class YeelightColorLightWithoutNightlightSwitch( """Representation of a Color Yeelight light.""" +class YeelightColorLightWithoutNightlightSwitchLight( + YeelightColorLightWithoutNightlightSwitch +): + """Representation of a Color Yeelight light.""" + + _attr_name = None + + class YeelightColorLightWithNightlightSwitch( YeelightNightLightSupport, YeelightColorLightSupport, YeelightGenericLight ): From f7dbe88ee02510db5b840a936bb48fd42e7a71cb Mon Sep 17 00:00:00 2001 From: Ian Harcombe Date: Fri, 4 Aug 2023 16:04:18 +0100 Subject: [PATCH 039/120] Fix metoffice visibility range sensor device class (#97763) * Fix for issue #97694 Issue #97694 points out that the visibility range is a string with a band of distances, not a single value, which is causing issues for front end components. Removed the device class to leave as an informational string value. * Removed *all* empty device_class statements * Missed an empty device_class :( --- homeassistant/components/metoffice/sensor.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/homeassistant/components/metoffice/sensor.py b/homeassistant/components/metoffice/sensor.py index 3bf50525ca9..fcb8e5b134e 100644 --- a/homeassistant/components/metoffice/sensor.py +++ b/homeassistant/components/metoffice/sensor.py @@ -51,14 +51,12 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( SensorEntityDescription( key="name", name="Station name", - device_class=None, icon="mdi:label-outline", entity_registry_enabled_default=False, ), SensorEntityDescription( key="weather", name="Weather", - device_class=None, icon="mdi:weather-sunny", # but will adapt to current conditions entity_registry_enabled_default=True, ), @@ -107,7 +105,6 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( SensorEntityDescription( key="visibility", name="Visibility", - device_class=None, icon="mdi:eye", entity_registry_enabled_default=False, ), @@ -115,14 +112,12 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( key="visibility_distance", name="Visibility distance", native_unit_of_measurement=UnitOfLength.KILOMETERS, - device_class=SensorDeviceClass.DISTANCE, icon="mdi:eye", entity_registry_enabled_default=False, ), SensorEntityDescription( key="uv", name="UV index", - device_class=None, native_unit_of_measurement=UV_INDEX, icon="mdi:weather-sunny-alert", entity_registry_enabled_default=True, @@ -130,7 +125,6 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( SensorEntityDescription( key="precipitation", name="Probability of precipitation", - device_class=None, native_unit_of_measurement=PERCENTAGE, icon="mdi:weather-rainy", entity_registry_enabled_default=True, From 01fad9b41c3fc71ad393d522bc333538e4b6fa60 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 5 Aug 2023 11:05:15 +0000 Subject: [PATCH 040/120] Don't assume that `battery_level` value is always present in Tractive `hw_info` (#97766) Don't assume that battery_level value is always present in hw_info --- homeassistant/components/tractive/device_tracker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tractive/device_tracker.py b/homeassistant/components/tractive/device_tracker.py index e9739819734..a97ea963362 100644 --- a/homeassistant/components/tractive/device_tracker.py +++ b/homeassistant/components/tractive/device_tracker.py @@ -43,7 +43,7 @@ class TractiveDeviceTracker(TractiveEntity, TrackerEntity): """Initialize tracker entity.""" super().__init__(user_id, item.trackable, item.tracker_details) - self._battery_level: int = item.hw_info["battery_level"] + self._battery_level: int | None = item.hw_info.get("battery_level") self._latitude: float = item.pos_report["latlong"][0] self._longitude: float = item.pos_report["latlong"][1] self._accuracy: int = item.pos_report["pos_uncertainty"] @@ -75,7 +75,7 @@ class TractiveDeviceTracker(TractiveEntity, TrackerEntity): return self._accuracy @property - def battery_level(self) -> int: + def battery_level(self) -> int | None: """Return the battery level of the device.""" return self._battery_level From cdc1de08ade66595e0961a80ce839710de4c4d43 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 4 Aug 2023 19:22:46 +0200 Subject: [PATCH 041/120] Improve counting of UniFi WLAN Clients sensor (#97785) --- homeassistant/components/unifi/sensor.py | 2 ++ tests/components/unifi/test_sensor.py | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/unifi/sensor.py b/homeassistant/components/unifi/sensor.py index 8cdc0dcbb71..ff5c58d7d6c 100644 --- a/homeassistant/components/unifi/sensor.py +++ b/homeassistant/components/unifi/sensor.py @@ -79,6 +79,8 @@ def async_wlan_client_value_fn(controller: UniFiController, wlan: Wlan) -> int: client.mac for client in controller.api.clients.values() if client.essid == wlan.name + and dt_util.utcnow() - dt_util.utc_from_timestamp(client.last_seen or 0) + < controller.option_detection_time ] ) diff --git a/tests/components/unifi/test_sensor.py b/tests/components/unifi/test_sensor.py index d619cd4c3c9..3d50df8ada9 100644 --- a/tests/components/unifi/test_sensor.py +++ b/tests/components/unifi/test_sensor.py @@ -470,6 +470,7 @@ async def test_wlan_client_sensors( wireless_client_1 = { "essid": "SSID 1", "is_wired": False, + "last_seen": dt_util.as_timestamp(dt_util.utcnow()), "mac": "00:00:00:00:00:01", "name": "Wireless client", "oui": "Producer", @@ -479,6 +480,7 @@ async def test_wlan_client_sensors( wireless_client_2 = { "essid": "SSID 2", "is_wired": False, + "last_seen": dt_util.as_timestamp(dt_util.utcnow()), "mac": "00:00:00:00:00:02", "name": "Wireless client2", "oui": "Producer2", @@ -526,9 +528,17 @@ async def test_wlan_client_sensors( # Verify state update - decreasing number wireless_client_1["essid"] = "SSID" - wireless_client_2["essid"] = "SSID" - mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_1) + + async_fire_time_changed(hass, datetime.utcnow() + DEFAULT_SCAN_INTERVAL) + await hass.async_block_till_done() + + ssid_1 = hass.states.get("sensor.ssid_1") + assert ssid_1.state == "1" + + # Verify state update - decreasing number + + wireless_client_2["last_seen"] = 0 mock_unifi_websocket(message=MessageKey.CLIENT, data=wireless_client_2) async_fire_time_changed(hass, datetime.utcnow() + DEFAULT_SCAN_INTERVAL) From 136b91b5398119203cfc23f6b63124775b3a63c3 Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Mon, 7 Aug 2023 15:59:46 +0200 Subject: [PATCH 042/120] Integration tado bump (#97791) * Bumping to PyTado 0.16 and adding test coverage * Removing comment * Upgrading the deprecated functions * Updating tests to support paramterization * Delete test_config_flow.py Reverting the tests, which will be placed in a different PR. * Revert "Delete test_config_flow.py" This reverts commit 1719ebc990a32d3309f241f8adc8262008ca4ff3. * Reverting back changes --- homeassistant/components/tado/__init__.py | 39 ++++++++++----------- homeassistant/components/tado/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/tado/__init__.py b/homeassistant/components/tado/__init__.py index 1cd21634c8e..b57d384124c 100644 --- a/homeassistant/components/tado/__init__.py +++ b/homeassistant/components/tado/__init__.py @@ -163,12 +163,11 @@ class TadoConnector: def setup(self): """Connect to Tado and fetch the zones.""" - self.tado = Tado(self._username, self._password) - self.tado.setDebugging(True) + self.tado = Tado(self._username, self._password, None, True) # Load zones and devices - self.zones = self.tado.getZones() - self.devices = self.tado.getDevices() - tado_home = self.tado.getMe()["homes"][0] + self.zones = self.tado.get_zones() + self.devices = self.tado.get_devices() + tado_home = self.tado.get_me()["homes"][0] self.home_id = tado_home["id"] self.home_name = tado_home["name"] @@ -181,7 +180,7 @@ class TadoConnector: def update_devices(self): """Update the device data from Tado.""" - devices = self.tado.getDevices() + devices = self.tado.get_devices() for device in devices: device_short_serial_no = device["shortSerialNo"] _LOGGER.debug("Updating device %s", device_short_serial_no) @@ -190,7 +189,7 @@ class TadoConnector: INSIDE_TEMPERATURE_MEASUREMENT in device["characteristics"]["capabilities"] ): - device[TEMP_OFFSET] = self.tado.getDeviceInfo( + device[TEMP_OFFSET] = self.tado.get_device_info( device_short_serial_no, TEMP_OFFSET ) except RuntimeError: @@ -218,7 +217,7 @@ class TadoConnector: def update_zones(self): """Update the zone data from Tado.""" try: - zone_states = self.tado.getZoneStates()["zoneStates"] + zone_states = self.tado.get_zone_states()["zoneStates"] except RuntimeError: _LOGGER.error("Unable to connect to Tado while updating zones") return @@ -230,7 +229,7 @@ class TadoConnector: """Update the internal data from Tado.""" _LOGGER.debug("Updating zone %s", zone_id) try: - data = self.tado.getZoneState(zone_id) + data = self.tado.get_zone_state(zone_id) except RuntimeError: _LOGGER.error("Unable to connect to Tado while updating zone %s", zone_id) return @@ -251,8 +250,8 @@ class TadoConnector: def update_home(self): """Update the home data from Tado.""" try: - self.data["weather"] = self.tado.getWeather() - self.data["geofence"] = self.tado.getHomeState() + self.data["weather"] = self.tado.get_weather() + self.data["geofence"] = self.tado.get_home_state() dispatcher_send( self.hass, SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "home", "data"), @@ -265,15 +264,15 @@ class TadoConnector: def get_capabilities(self, zone_id): """Return the capabilities of the devices.""" - return self.tado.getCapabilities(zone_id) + return self.tado.get_capabilities(zone_id) def get_auto_geofencing_supported(self): """Return whether the Tado Home supports auto geofencing.""" - return self.tado.getAutoGeofencingSupported() + return self.tado.get_auto_geofencing_supported() def reset_zone_overlay(self, zone_id): """Reset the zone back to the default operation.""" - self.tado.resetZoneOverlay(zone_id) + self.tado.reset_zone_overlay(zone_id) self.update_zone(zone_id) def set_presence( @@ -282,11 +281,11 @@ class TadoConnector: ): """Set the presence to home, away or auto.""" if presence == PRESET_AWAY: - self.tado.setAway() + self.tado.set_away() elif presence == PRESET_HOME: - self.tado.setHome() + self.tado.set_home() elif presence == PRESET_AUTO: - self.tado.setAuto() + self.tado.set_auto() # Update everything when changing modes self.update_zones() @@ -320,7 +319,7 @@ class TadoConnector: ) try: - self.tado.setZoneOverlay( + self.tado.set_zone_overlay( zone_id, overlay_mode, temperature, @@ -340,7 +339,7 @@ class TadoConnector: def set_zone_off(self, zone_id, overlay_mode, device_type="HEATING"): """Set a zone to off.""" try: - self.tado.setZoneOverlay( + self.tado.set_zone_overlay( zone_id, overlay_mode, None, None, device_type, "OFF" ) except RequestException as exc: @@ -351,6 +350,6 @@ class TadoConnector: def set_temperature_offset(self, device_id, offset): """Set temperature offset of device.""" try: - self.tado.setTempOffset(device_id, offset) + self.tado.set_temp_offset(device_id, offset) except RequestException as exc: _LOGGER.error("Could not set temperature offset: %s", exc) diff --git a/homeassistant/components/tado/manifest.json b/homeassistant/components/tado/manifest.json index 62f7a377239..bea608514bd 100644 --- a/homeassistant/components/tado/manifest.json +++ b/homeassistant/components/tado/manifest.json @@ -14,5 +14,5 @@ }, "iot_class": "cloud_polling", "loggers": ["PyTado"], - "requirements": ["python-tado==0.15.0"] + "requirements": ["python-tado==0.16.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 21d10628ecb..5ca5541b9de 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2159,7 +2159,7 @@ python-smarttub==0.0.33 python-songpal==0.15.2 # homeassistant.components.tado -python-tado==0.15.0 +python-tado==0.16.0 # homeassistant.components.telegram_bot python-telegram-bot==13.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5cb970c7132..64e7e7ac03b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1588,7 +1588,7 @@ python-smarttub==0.0.33 python-songpal==0.15.2 # homeassistant.components.tado -python-tado==0.15.0 +python-tado==0.16.0 # homeassistant.components.telegram_bot python-telegram-bot==13.1 From 19d6c0c9490d99380627934ba48418168272b5bc Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 7 Aug 2023 05:23:52 +0200 Subject: [PATCH 043/120] Ensure webhooks take HA cloud into account (#97801) * Ensure webhooks take HA cloud into account * Avoid circular import --- homeassistant/components/webhook/__init__.py | 28 +++++++++++++------- tests/components/webhook/test_init.py | 14 +++++++++- tests/components/webhook/test_trigger.py | 20 +++++++++++--- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/webhook/__init__.py b/homeassistant/components/webhook/__init__.py index 9711c30b19e..5f82ca54283 100644 --- a/homeassistant/components/webhook/__init__.py +++ b/homeassistant/components/webhook/__init__.py @@ -145,16 +145,26 @@ async def async_handle_webhook( return Response(status=HTTPStatus.METHOD_NOT_ALLOWED) if webhook["local_only"] in (True, None) and not isinstance(request, MockRequest): - if TYPE_CHECKING: - assert isinstance(request, Request) - assert request.remote is not None - try: - remote = ip_address(request.remote) - except ValueError: - _LOGGER.debug("Unable to parse remote ip %s", request.remote) - return Response(status=HTTPStatus.OK) + if has_cloud := "cloud" in hass.config.components: + from hass_nabucasa import remote # pylint: disable=import-outside-toplevel - if not network.is_local(remote): + is_local = True + if has_cloud and remote.is_cloud_request.get(): + is_local = False + else: + if TYPE_CHECKING: + assert isinstance(request, Request) + assert request.remote is not None + + try: + request_remote = ip_address(request.remote) + except ValueError: + _LOGGER.debug("Unable to parse remote ip %s", request.remote) + return Response(status=HTTPStatus.OK) + + is_local = network.is_local(request_remote) + + if not is_local: _LOGGER.warning("Received remote request for local webhook %s", webhook_id) if webhook["local_only"]: return Response(status=HTTPStatus.OK) diff --git a/tests/components/webhook/test_init.py b/tests/components/webhook/test_init.py index ff0346a3d8b..fbe0da15853 100644 --- a/tests/components/webhook/test_init.py +++ b/tests/components/webhook/test_init.py @@ -1,7 +1,7 @@ """Test the webhook component.""" from http import HTTPStatus from ipaddress import ip_address -from unittest.mock import patch +from unittest.mock import Mock, patch from aiohttp import web import pytest @@ -206,6 +206,8 @@ async def test_webhook_not_allowed_method(hass: HomeAssistant) -> None: async def test_webhook_local_only(hass: HomeAssistant, mock_client) -> None: """Test posting a webhook with local only.""" + hass.config.components.add("cloud") + hooks = [] webhook_id = webhook.async_generate_id() @@ -234,6 +236,16 @@ async def test_webhook_local_only(hass: HomeAssistant, mock_client) -> None: # No hook received assert len(hooks) == 1 + # Request from Home Assistant Cloud remote UI + with patch( + "hass_nabucasa.remote.is_cloud_request", Mock(get=Mock(return_value=True)) + ): + resp = await mock_client.post(f"/api/webhook/{webhook_id}", json={"data": True}) + + # No hook received + assert resp.status == HTTPStatus.OK + assert len(hooks) == 1 + async def test_listing_webhook( hass: HomeAssistant, diff --git a/tests/components/webhook/test_trigger.py b/tests/components/webhook/test_trigger.py index 392ab58a30f..990482c500e 100644 --- a/tests/components/webhook/test_trigger.py +++ b/tests/components/webhook/test_trigger.py @@ -1,6 +1,6 @@ """The tests for the webhook automation trigger.""" from ipaddress import ip_address -from unittest.mock import patch +from unittest.mock import Mock, patch import pytest @@ -68,6 +68,9 @@ async def test_webhook_post( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator ) -> None: """Test triggering with a POST webhook.""" + # Set up fake cloud + hass.config.components.add("cloud") + events = [] @callback @@ -114,6 +117,16 @@ async def test_webhook_post( await hass.async_block_till_done() assert len(events) == 1 + # Request from Home Assistant Cloud remote UI + with patch( + "hass_nabucasa.remote.is_cloud_request", Mock(get=Mock(return_value=True)) + ): + await client.post("/api/webhook/post_webhook", data={"hello": "world"}) + + # No hook received + await hass.async_block_till_done() + assert len(events) == 1 + async def test_webhook_allowed_methods_internet( hass: HomeAssistant, hass_client_no_auth: ClientSessionGenerator @@ -141,7 +154,6 @@ async def test_webhook_allowed_methods_internet( }, "action": { "event": "test_success", - "event_data_template": {"hello": "yo {{ trigger.data.hello }}"}, }, } }, @@ -150,7 +162,7 @@ async def test_webhook_allowed_methods_internet( client = await hass_client_no_auth() - await client.post("/api/webhook/post_webhook", data={"hello": "world"}) + await client.post("/api/webhook/post_webhook") await hass.async_block_till_done() assert len(events) == 0 @@ -160,7 +172,7 @@ async def test_webhook_allowed_methods_internet( "homeassistant.components.webhook.ip_address", return_value=ip_address("123.123.123.123"), ): - await client.put("/api/webhook/post_webhook", data={"hello": "world"}) + await client.put("/api/webhook/post_webhook") await hass.async_block_till_done() assert len(events) == 1 From 922f3f2816aefb4da753f22c9bb01dc5dc6a631a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 4 Aug 2023 22:01:08 -1000 Subject: [PATCH 044/120] Bump aiohomekit to 2.6.13 (#97820) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index 8cc80ef864e..01b85ef6bbb 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.12"], + "requirements": ["aiohomekit==2.6.13"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 5ca5541b9de..a4bfda7ab02 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -249,7 +249,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.12 +aiohomekit==2.6.13 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 64e7e7ac03b..21ef54c3582 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -227,7 +227,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.12 +aiohomekit==2.6.13 # homeassistant.components.emulated_hue # homeassistant.components.http From 70730e4170344563fe7c8da26306a30c198b266a Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sat, 5 Aug 2023 19:43:22 +0200 Subject: [PATCH 045/120] Fix Samsung syncthru device info (#97843) Fix Samsung device info --- homeassistant/components/syncthru/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/syncthru/__init__.py b/homeassistant/components/syncthru/__init__.py index f77f68450a4..424b81ac800 100644 --- a/homeassistant/components/syncthru/__init__.py +++ b/homeassistant/components/syncthru/__init__.py @@ -67,7 +67,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: config_entry_id=entry.entry_id, configuration_url=printer.url, connections=device_connections(printer), - default_manufacturer="Samsung", + manufacturer="Samsung", identifiers=device_identifiers(printer), model=printer.model(), name=printer.hostname(), From 871ab7a8185468b6dcf2d680d1a71ac42fc42899 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Tue, 8 Aug 2023 19:15:06 +0200 Subject: [PATCH 046/120] Fallback to get_hosts_info on older Fritz!OS in AVM Fritz!Tools (#97844) --- homeassistant/components/fritz/common.py | 119 +++++++++++++++++------ 1 file changed, 89 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index 8dfe5be9308..531c05eea4a 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -160,6 +160,15 @@ HostAttributes = TypedDict( ) +class HostInfo(TypedDict): + """FRITZ!Box host info class.""" + + mac: str + name: str + ip: str + status: bool + + class UpdateCoordinatorDataType(TypedDict): """Update coordinator data type.""" @@ -380,16 +389,86 @@ class FritzBoxTools( """Event specific per FRITZ!Box entry to signal updates in devices.""" return f"{DOMAIN}-device-update-{self._unique_id}" - async def _async_update_hosts_info(self) -> list[HostAttributes]: - """Retrieve latest hosts information from the FRITZ!Box.""" + async def _async_get_wan_access(self, ip_address: str) -> bool | None: + """Get WAN access rule for given IP address.""" try: - return await self.hass.async_add_executor_job( - self.fritz_hosts.get_hosts_attributes + wan_access = await self.hass.async_add_executor_job( + partial( + self.connection.call_action, + "X_AVM-DE_HostFilter:1", + "GetWANAccessByIP", + NewIPv4Address=ip_address, + ) ) + return not wan_access.get("NewDisallow") + except FRITZ_EXCEPTIONS as ex: + _LOGGER.debug( + ( + "could not get WAN access rule for client device with IP '%s'," + " error: %s" + ), + ip_address, + ex, + ) + return None + + async def _async_update_hosts_info(self) -> dict[str, Device]: + """Retrieve latest hosts information from the FRITZ!Box.""" + hosts_attributes: list[HostAttributes] = [] + hosts_info: list[HostInfo] = [] + try: + try: + hosts_attributes = await self.hass.async_add_executor_job( + self.fritz_hosts.get_hosts_attributes + ) + except FritzActionError: + hosts_info = await self.hass.async_add_executor_job( + self.fritz_hosts.get_hosts_info + ) except Exception as ex: # pylint: disable=[broad-except] if not self.hass.is_stopping: raise HomeAssistantError("Error refreshing hosts info") from ex - return [] + + hosts: dict[str, Device] = {} + if hosts_attributes: + for attributes in hosts_attributes: + if not attributes.get("MACAddress"): + continue + + if (wan_access := attributes.get("X_AVM-DE_WANAccess")) is not None: + wan_access_result = "granted" in wan_access + else: + wan_access_result = None + + hosts[attributes["MACAddress"]] = Device( + name=attributes["HostName"], + connected=attributes["Active"], + connected_to="", + connection_type="", + ip_address=attributes["IPAddress"], + ssid=None, + wan_access=wan_access_result, + ) + else: + for info in hosts_info: + if not info.get("mac"): + continue + + if info["ip"]: + wan_access_result = await self._async_get_wan_access(info["ip"]) + else: + wan_access_result = None + + hosts[info["mac"]] = Device( + name=info["name"], + connected=info["status"], + connected_to="", + connection_type="", + ip_address=info["ip"], + ssid=None, + wan_access=wan_access_result, + ) + return hosts def _update_device_info(self) -> tuple[bool, str | None, str | None]: """Retrieve latest device information from the FRITZ!Box.""" @@ -464,25 +543,7 @@ class FritzBoxTools( consider_home = _default_consider_home new_device = False - hosts = {} - for host in await self._async_update_hosts_info(): - if not host.get("MACAddress"): - continue - - if (wan_access := host.get("X_AVM-DE_WANAccess")) is not None: - wan_access_result = "granted" in wan_access - else: - wan_access_result = None - - hosts[host["MACAddress"]] = Device( - name=host["HostName"], - connected=host["Active"], - connected_to="", - connection_type="", - ip_address=host["IPAddress"], - ssid=None, - wan_access=wan_access_result, - ) + hosts = await self._async_update_hosts_info() if not self.fritz_status.device_has_mesh_support or ( self._options @@ -584,9 +645,7 @@ class FritzBoxTools( self, config_entry: ConfigEntry | None = None ) -> None: """Trigger device trackers cleanup.""" - device_hosts_list = await self.hass.async_add_executor_job( - self.fritz_hosts.get_hosts_attributes - ) + device_hosts = await self._async_update_hosts_info() entity_reg: er.EntityRegistry = er.async_get(self.hass) if config_entry is None: @@ -601,9 +660,9 @@ class FritzBoxTools( device_hosts_macs = set() device_hosts_names = set() - for device in device_hosts_list: - device_hosts_macs.add(device["MACAddress"]) - device_hosts_names.add(device["HostName"]) + for mac, device in device_hosts.items(): + device_hosts_macs.add(mac) + device_hosts_names.add(device.name) for entry in ha_entity_reg_list: if entry.original_name is None: From 9b090d8c7bad305acff3661c307096c2809ea68d Mon Sep 17 00:00:00 2001 From: G Johansson Date: Sat, 5 Aug 2023 16:21:39 +0200 Subject: [PATCH 047/120] Fix Command Line template error when data is None (#97845) Command Line template error --- .../components/command_line/sensor.py | 4 +- tests/components/command_line/test_sensor.py | 40 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/command_line/sensor.py b/homeassistant/components/command_line/sensor.py index dd5ad2d5190..2ccbdbc4785 100644 --- a/homeassistant/components/command_line/sensor.py +++ b/homeassistant/components/command_line/sensor.py @@ -207,7 +207,8 @@ class CommandSensor(ManualTriggerEntity, SensorEntity): self._process_manual_data(value) return - if self._value_template is not None: + self._attr_native_value = None + if self._value_template is not None and value is not None: value = self._value_template.async_render_with_possible_json_value( value, None, @@ -221,7 +222,6 @@ class CommandSensor(ManualTriggerEntity, SensorEntity): self._process_manual_data(value) return - self._attr_native_value = None if value is not None: self._attr_native_value = async_parse_date_datetime( value, self.entity_id, self.device_class diff --git a/tests/components/command_line/test_sensor.py b/tests/components/command_line/test_sensor.py index bc24ff5419f..db6dd277e1f 100644 --- a/tests/components/command_line/test_sensor.py +++ b/tests/components/command_line/test_sensor.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio from datetime import timedelta +import subprocess from typing import Any from unittest.mock import patch @@ -16,7 +17,7 @@ from homeassistant.components.homeassistant import ( SERVICE_UPDATE_ENTITY, ) from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN -from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er import homeassistant.helpers.issue_registry as ir @@ -697,3 +698,40 @@ async def test_scrape_sensor_device_date( entity_state = hass.states.get("sensor.test") assert entity_state assert entity_state.state == "2022-01-17" + + +async def test_template_not_error_when_data_is_none( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test command sensor with template not logging error when data is None.""" + + with patch( + "homeassistant.components.command_line.utils.subprocess.check_output", + side_effect=subprocess.CalledProcessError, + ): + await setup.async_setup_component( + hass, + DOMAIN, + { + "command_line": [ + { + "sensor": { + "name": "Test", + "command": "failed command", + "unit_of_measurement": "MB", + "value_template": "{{ (value.split('\t')[0]|int(0)/1000)|round(3) }}", + } + } + ] + }, + ) + await hass.async_block_till_done() + + entity_state = hass.states.get("sensor.test") + assert entity_state + assert entity_state.state == STATE_UNKNOWN + + assert ( + "Template variable error: 'None' has no attribute 'split' when rendering" + not in caplog.text + ) From 60da270372437f6ba57431a6d9277c7ae7bfcf39 Mon Sep 17 00:00:00 2001 From: MarkGodwin <10632972+MarkGodwin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:59:03 +0100 Subject: [PATCH 048/120] Bump Omada API version to fix #96193 (#97848) --- homeassistant/components/tplink_omada/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_omada/manifest.json b/homeassistant/components/tplink_omada/manifest.json index 795e6adf5b7..9c303b24661 100644 --- a/homeassistant/components/tplink_omada/manifest.json +++ b/homeassistant/components/tplink_omada/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/tplink_omada", "integration_type": "hub", "iot_class": "local_polling", - "requirements": ["tplink_omada_client==1.2.4"] + "requirements": ["tplink_omada_client==1.3.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index a4bfda7ab02..8905ad802b7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2563,7 +2563,7 @@ total-connect-client==2023.2 tp-connected==0.0.4 # homeassistant.components.tplink_omada -tplink_omada_client==1.2.4 +tplink_omada_client==1.3.2 # homeassistant.components.transmission transmission-rpc==4.1.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 21ef54c3582..43026a157ec 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1869,7 +1869,7 @@ toonapi==0.2.1 total-connect-client==2023.2 # homeassistant.components.tplink_omada -tplink_omada_client==1.2.4 +tplink_omada_client==1.3.2 # homeassistant.components.transmission transmission-rpc==4.1.5 From 379e144f843582caa578d0702c6bee3fd6192c21 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Sat, 5 Aug 2023 19:02:44 +0200 Subject: [PATCH 049/120] Bump pysensibo to 1.0.33 (#97853) * Bump pysensibo to 1.0.33 * for loop --- .../components/sensibo/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/sensibo/fixtures/data.json | 157 ++++++++++++++++++ tests/components/sensibo/test_climate.py | 19 ++- 5 files changed, 178 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensibo/manifest.json b/homeassistant/components/sensibo/manifest.json index 26182102442..42964ddce8f 100644 --- a/homeassistant/components/sensibo/manifest.json +++ b/homeassistant/components/sensibo/manifest.json @@ -15,5 +15,5 @@ "iot_class": "cloud_polling", "loggers": ["pysensibo"], "quality_scale": "platinum", - "requirements": ["pysensibo==1.0.32"] + "requirements": ["pysensibo==1.0.33"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8905ad802b7..a14b17b2c55 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1982,7 +1982,7 @@ pysabnzbd==1.1.1 pysaj==0.0.16 # homeassistant.components.sensibo -pysensibo==1.0.32 +pysensibo==1.0.33 # homeassistant.components.serial # homeassistant.components.zha diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 43026a157ec..70b5b3d9e24 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1474,7 +1474,7 @@ pyrympro==0.0.7 pysabnzbd==1.1.1 # homeassistant.components.sensibo -pysensibo==1.0.32 +pysensibo==1.0.33 # homeassistant.components.serial # homeassistant.components.zha diff --git a/tests/components/sensibo/fixtures/data.json b/tests/components/sensibo/fixtures/data.json index 7db7b4a7c4a..8be6d1e173a 100644 --- a/tests/components/sensibo/fixtures/data.json +++ b/tests/components/sensibo/fixtures/data.json @@ -547,6 +547,163 @@ "autoOffEnabled": false, "antiMoldTimer": null, "antiMoldConfig": null + }, + { + "isGeofenceOnEnterEnabledForThisUser": false, + "isClimateReactGeofenceOnEnterEnabledForThisUser": false, + "isMotionGeofenceOnEnterEnabled": false, + "isOwner": true, + "id": "BBZZBBZZ", + "qrId": "AAAAAAAACC", + "temperatureUnit": "C", + "room": { + "uid": "99YY99YY", + "name": "Bedroom", + "icon": "Diningroom" + }, + "acState": { + "timestamp": { + "time": "2022-04-30T11:23:30.067312Z", + "secondsAgo": -1 + }, + "on": false + }, + "lastStateChange": { + "time": "2022-04-30T11:21:41Z", + "secondsAgo": 108 + }, + "lastStateChangeToOn": { + "time": "2022-04-30T09:43:26Z", + "secondsAgo": 6003 + }, + "lastStateChangeToOff": { + "time": "2022-04-30T11:21:37Z", + "secondsAgo": 112 + }, + "location": { + "id": "ZZZZZZZZZZYY", + "name": "Home", + "latLon": [58.9806976, 20.5864297], + "address": ["Sealand 99", "Some county"], + "country": "United Country", + "createTime": { + "time": "2020-03-21T15:44:15Z", + "secondsAgo": 66543240 + } + }, + "connectionStatus": { + "isAlive": true, + "lastSeen": { + "time": "2022-04-30T11:23:20.642798Z", + "secondsAgo": 9 + } + }, + "firmwareVersion": "PUR00111", + "firmwareType": "pure-esp32", + "productModel": "pure", + "configGroup": "stable", + "currentlyAvailableFirmwareVersion": "PUR00111", + "cleanFiltersNotificationEnabled": false, + "shouldShowFilterCleaningNotification": false, + "isGeofenceOnExitEnabled": false, + "isClimateReactGeofenceOnExitEnabled": false, + "isMotionGeofenceOnExitEnabled": false, + "serial": "0987654321", + "sensorsCalibration": { + "temperature": 0.0, + "humidity": 0.0 + }, + "motionSensors": [], + "tags": [], + "timer": null, + "schedules": [], + "motionConfig": null, + "filtersCleaning": { + "acOnSecondsSinceLastFiltersClean": 415560, + "filtersCleanSecondsThreshold": 14256000, + "lastFiltersCleanTime": { + "time": "2022-04-23T15:58:45Z", + "secondsAgo": 588284 + }, + "shouldCleanFilters": false + }, + "serviceSubscriptions": [], + "roomIsOccupied": null, + "mainMeasurementsSensor": null, + "pureBoostConfig": null, + "warrantyEligible": "no", + "warrantyEligibleUntil": { + "time": "2022-04-10T09:58:58Z", + "secondsAgo": 1733071 + }, + "features": ["optimusTrial", "softShowPlus"], + "runningHealthcheck": null, + "lastHealthcheck": null, + "lastACStateChange": { + "id": "AA22", + "time": { + "time": "2022-04-30T11:21:37Z", + "secondsAgo": 112 + }, + "status": "Success", + "acState": { + "timestamp": { + "time": "2022-04-30T11:23:30.090144Z", + "secondsAgo": -1 + }, + "on": false, + "mode": "fan", + "fanLevel": "low", + "light": "on" + }, + "resultingAcState": { + "timestamp": { + "time": "2022-04-30T11:23:30.090185Z", + "secondsAgo": -1 + }, + "on": false, + "mode": "fan", + "fanLevel": "low", + "light": "on" + }, + "changedProperties": ["on"], + "reason": "UserRequest", + "failureReason": null, + "resolveTime": { + "time": "2022-04-30T11:21:37Z", + "secondsAgo": 112 + }, + "causedByScheduleId": null, + "causedByScheduleType": null + }, + "homekitSupported": true, + "remoteCapabilities": null, + "remote": { + "toggle": false, + "window": false + }, + "remoteFlavor": "Eccentric Eagle", + "remoteAlternatives": [], + "smartMode": null, + "measurements": { + "time": { + "time": "2022-04-30T11:23:20.642798Z", + "secondsAgo": 9 + }, + "rssi": -58, + "pm25": 1, + "motion": false, + "roomIsOccupied": null + }, + "accessPoint": { + "ssid": "Sensibo-09876", + "password": null + }, + "macAddress": "00:01:00:01:00:01", + "autoOffMinutes": null, + "autoOffEnabled": false, + "antiMoldTimer": null, + "antiMoldConfig": null } ] } diff --git a/tests/components/sensibo/test_climate.py b/tests/components/sensibo/test_climate.py index 4e856d396c1..56a7a8c902c 100644 --- a/tests/components/sensibo/test_climate.py +++ b/tests/components/sensibo/test_climate.py @@ -76,12 +76,16 @@ async def test_climate_find_valid_targets() -> None: async def test_climate( - hass: HomeAssistant, load_int: ConfigEntry, get_data: SensiboData + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, + get_data: SensiboData, + load_int: ConfigEntry, ) -> None: """Test the Sensibo climate.""" state1 = hass.states.get("climate.hallway") state2 = hass.states.get("climate.kitchen") + state3 = hass.states.get("climate.bedroom") assert state1.state == "heat" assert state1.attributes == { @@ -113,6 +117,19 @@ async def test_climate( assert state2.state == "off" + assert not state3 + found_log = False + logs = caplog.get_records("setup") + for log in logs: + if ( + log.message + == "Device Bedroom not correctly registered with Sensibo cloud. Skipping device" + ): + found_log = True + break + + assert found_log + async def test_climate_fan( hass: HomeAssistant, From 5aa96aa6f66b8c6467ad4a824440ed38240be59d Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Sat, 5 Aug 2023 18:48:13 +0200 Subject: [PATCH 050/120] Add missing translation key to Gardena Bluetooth (#97855) --- homeassistant/components/gardena_bluetooth/strings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/gardena_bluetooth/strings.json b/homeassistant/components/gardena_bluetooth/strings.json index 1d9a281fdbc..1fc6e10b5a6 100644 --- a/homeassistant/components/gardena_bluetooth/strings.json +++ b/homeassistant/components/gardena_bluetooth/strings.json @@ -15,7 +15,8 @@ "cannot_connect": "Failed to connect: {error}" }, "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]" + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]" } }, "entity": { From 2b3bf3636457a1ef391d99e1cf4c3975560a19f0 Mon Sep 17 00:00:00 2001 From: Richard Kroegel <42204099+rikroe@users.noreply.github.com> Date: Sat, 5 Aug 2023 20:08:14 +0200 Subject: [PATCH 051/120] Bump bimmer_connected to 0.13.9, fix notify (#97860) Bump bimmer_connected to 0.13.9 Co-authored-by: rikroe --- homeassistant/components/bmw_connected_drive/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/bmw_connected_drive/manifest.json b/homeassistant/components/bmw_connected_drive/manifest.json index 82426fbce08..ff2804a8c04 100644 --- a/homeassistant/components/bmw_connected_drive/manifest.json +++ b/homeassistant/components/bmw_connected_drive/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive", "iot_class": "cloud_polling", "loggers": ["bimmer_connected"], - "requirements": ["bimmer-connected==0.13.8"] + "requirements": ["bimmer-connected==0.13.9"] } diff --git a/requirements_all.txt b/requirements_all.txt index a14b17b2c55..4caae5560fa 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -503,7 +503,7 @@ beautifulsoup4==4.11.1 bellows==0.35.8 # homeassistant.components.bmw_connected_drive -bimmer-connected==0.13.8 +bimmer-connected==0.13.9 # homeassistant.components.bizkaibus bizkaibus==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 70b5b3d9e24..358c30d515c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -427,7 +427,7 @@ beautifulsoup4==4.11.1 bellows==0.35.8 # homeassistant.components.bmw_connected_drive -bimmer-connected==0.13.8 +bimmer-connected==0.13.9 # homeassistant.components.bluetooth bleak-retry-connector==3.1.1 From 80a473682e061030b882e642025ecbc49f93adf3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 5 Aug 2023 12:31:50 -1000 Subject: [PATCH 052/120] Do not fire homekit_controller events from IP polling (#97869) * Fix homekit_controller triggers when value is None * fixes * cover --- .../homekit_controller/device_trigger.py | 25 ++++++++++++------- .../homekit_controller/test_device_trigger.py | 8 ++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/homekit_controller/device_trigger.py b/homeassistant/components/homekit_controller/device_trigger.py index bbc56ddd4a4..4f44cea34f4 100644 --- a/homeassistant/components/homekit_controller/device_trigger.py +++ b/homeassistant/components/homekit_controller/device_trigger.py @@ -80,11 +80,11 @@ class TriggerSource: self._iid_trigger_keys.setdefault(iid, set()).add(trigger_key) await connection.add_watchable_characteristics([(aid, iid)]) - def fire(self, iid: int, value: dict[str, Any]) -> None: + def fire(self, iid: int, ev: dict[str, Any]) -> None: """Process events that have been received from a HomeKit accessory.""" for trigger_key in self._iid_trigger_keys.get(iid, set()): for event_handler in self._callbacks.get(trigger_key, []): - event_handler(value) + event_handler(ev) def async_get_triggers(self) -> Generator[tuple[str, str], None, None]: """List device triggers for HomeKit devices.""" @@ -99,20 +99,23 @@ class TriggerSource: ) -> CALLBACK_TYPE: """Attach a trigger.""" trigger_data = trigger_info["trigger_data"] - trigger_key = (config[CONF_TYPE], config[CONF_SUBTYPE]) + type_: str = config[CONF_TYPE] + sub_type: str = config[CONF_SUBTYPE] + trigger_key = (type_, sub_type) job = HassJob(action) + trigger_callbacks = self._callbacks.setdefault(trigger_key, []) + hass = self._hass @callback - def event_handler(char: dict[str, Any]) -> None: - if config[CONF_SUBTYPE] != HK_TO_HA_INPUT_EVENT_VALUES[char["value"]]: + def event_handler(ev: dict[str, Any]) -> None: + if sub_type != HK_TO_HA_INPUT_EVENT_VALUES[ev["value"]]: return - self._hass.async_run_hass_job(job, {"trigger": {**trigger_data, **config}}) + hass.async_run_hass_job(job, {"trigger": {**trigger_data, **config}}) - self._callbacks.setdefault(trigger_key, []).append(event_handler) + trigger_callbacks.append(event_handler) def async_remove_handler(): - if trigger_key in self._callbacks: - self._callbacks[trigger_key].remove(event_handler) + trigger_callbacks.remove(event_handler) return async_remove_handler @@ -259,6 +262,10 @@ def async_fire_triggers(conn: HKDevice, events: dict[tuple[int, int], dict[str, if not trigger_sources: return for (aid, iid), ev in events.items(): + # If the value is None, we received the event via polling + # and we don't want to trigger on that + if ev["value"] is None: + continue if aid in conn.devices: device_id = conn.devices[aid] if source := trigger_sources.get(device_id): diff --git a/tests/components/homekit_controller/test_device_trigger.py b/tests/components/homekit_controller/test_device_trigger.py index 757823aba9b..c7e5005446f 100644 --- a/tests/components/homekit_controller/test_device_trigger.py +++ b/tests/components/homekit_controller/test_device_trigger.py @@ -425,6 +425,14 @@ async def test_handle_events_late_setup(hass: HomeAssistant, utcnow, calls) -> N assert len(calls) == 1 assert calls[0].data["some"] == "device - button1 - single_press - 0" + # Make sure automation doesn't trigger for a polled None + helper.pairing.testing.update_named_service( + "Button 1", {CharacteristicsTypes.INPUT_EVENT: None} + ) + + await hass.async_block_till_done() + assert len(calls) == 1 + # Make sure automation doesn't trigger for long press helper.pairing.testing.update_named_service( "Button 1", {CharacteristicsTypes.INPUT_EVENT: 1} From a8c181b7fc3416a23abc59f1b2d41a2a7d9079d9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 6 Aug 2023 11:11:03 -1000 Subject: [PATCH 053/120] Avoid polling event characteristic in homekit_controller (#97877) --- homeassistant/components/homekit_controller/entity.py | 6 +++++- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/homekit_controller/entity.py b/homeassistant/components/homekit_controller/entity.py index 046dc9f17ec..6ebe777d5f8 100644 --- a/homeassistant/components/homekit_controller/entity.py +++ b/homeassistant/components/homekit_controller/entity.py @@ -5,6 +5,7 @@ from typing import Any from aiohomekit.model import Accessory from aiohomekit.model.characteristics import ( + EVENT_CHARACTERISTICS, Characteristic, CharacteristicPermissions, CharacteristicsTypes, @@ -111,7 +112,10 @@ class HomeKitEntity(Entity): def _setup_characteristic(self, char: Characteristic) -> None: """Configure an entity based on a HomeKit characteristics metadata.""" # Build up a list of (aid, iid) tuples to poll on update() - if CharacteristicPermissions.paired_read in char.perms: + if ( + CharacteristicPermissions.paired_read in char.perms + and char.type not in EVENT_CHARACTERISTICS + ): self.pollable_characteristics.append((self._aid, char.iid)) # Build up a list of (aid, iid) tuples to subscribe to diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index 01b85ef6bbb..d26b15bdc7a 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.13"], + "requirements": ["aiohomekit==2.6.14"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 4caae5560fa..a334109ec14 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -249,7 +249,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.13 +aiohomekit==2.6.14 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 358c30d515c..aa4b47d4247 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -227,7 +227,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.13 +aiohomekit==2.6.14 # homeassistant.components.emulated_hue # homeassistant.components.http From c417b1e61180b0e4f7145002ef5176a3f5f3f98d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 5 Aug 2023 19:14:18 -1000 Subject: [PATCH 054/120] Fix handling HomeKit events when the char is in error state (#97884) --- .../components/homekit_controller/device_trigger.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/homekit_controller/device_trigger.py b/homeassistant/components/homekit_controller/device_trigger.py index 4f44cea34f4..9eab0fbb098 100644 --- a/homeassistant/components/homekit_controller/device_trigger.py +++ b/homeassistant/components/homekit_controller/device_trigger.py @@ -262,14 +262,13 @@ def async_fire_triggers(conn: HKDevice, events: dict[tuple[int, int], dict[str, if not trigger_sources: return for (aid, iid), ev in events.items(): - # If the value is None, we received the event via polling - # and we don't want to trigger on that - if ev["value"] is None: - continue if aid in conn.devices: device_id = conn.devices[aid] if source := trigger_sources.get(device_id): - source.fire(iid, ev) + # If the value is None, we received the event via polling + # and we don't want to trigger on that + if ev.get("value") is not None: + source.fire(iid, ev) async def async_get_triggers( From 79bb857e06e6fa813e7de9e87fc7ceb16937872e Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 6 Aug 2023 16:34:14 -0400 Subject: [PATCH 055/120] Bump python-roborock to 0.32.2 (#97907) * bump to 0.32.2 * fix test --- homeassistant/components/roborock/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/roborock/conftest.py | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index eda6a5609a2..05fff332c67 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/roborock", "iot_class": "local_polling", "loggers": ["roborock"], - "requirements": ["python-roborock==0.31.1"] + "requirements": ["python-roborock==0.32.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index a334109ec14..b44914a9596 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2150,7 +2150,7 @@ python-qbittorrent==0.4.3 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==0.31.1 +python-roborock==0.32.2 # homeassistant.components.smarttub python-smarttub==0.0.33 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index aa4b47d4247..79edfa25e46 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1579,7 +1579,7 @@ python-picnic-api==1.1.0 python-qbittorrent==0.4.3 # homeassistant.components.roborock -python-roborock==0.31.1 +python-roborock==0.32.2 # homeassistant.components.smarttub python-smarttub==0.0.33 diff --git a/tests/components/roborock/conftest.py b/tests/components/roborock/conftest.py index eb281076825..ef841769f8d 100644 --- a/tests/components/roborock/conftest.py +++ b/tests/components/roborock/conftest.py @@ -67,6 +67,10 @@ async def setup_entry( return_value=PROP, ), patch( "homeassistant.components.roborock.coordinator.RoborockLocalClient.send_message" + ), patch( + "homeassistant.components.roborock.RoborockMqttClient._wait_response" + ), patch( + "homeassistant.components.roborock.coordinator.RoborockLocalClient._wait_response" ): assert await async_setup_component(hass, DOMAIN, {}) await hass.async_block_till_done() From a276fd444ec458ac97ca2c6b7a2034fc7b9af4ef Mon Sep 17 00:00:00 2001 From: jan iversen Date: Tue, 8 Aug 2023 16:09:53 +0200 Subject: [PATCH 056/120] modbus: Adjust read count by slave_count (#97908) --- homeassistant/components/modbus/sensor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index ca8246577fd..a1c89677e4f 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -49,7 +49,7 @@ async def async_setup_platform( hub = get_hub(hass, discovery_info[CONF_NAME]) for entry in discovery_info[CONF_SENSORS]: slave_count = entry.get(CONF_SLAVE_COUNT, 0) - sensor = ModbusRegisterSensor(hub, entry) + sensor = ModbusRegisterSensor(hub, entry, slave_count) if slave_count > 0: sensors.extend(await sensor.async_setup_slaves(hass, slave_count, entry)) sensors.append(sensor) @@ -63,9 +63,12 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity): self, hub: ModbusHub, entry: dict[str, Any], + slave_count: int, ) -> None: """Initialize the modbus register sensor.""" super().__init__(hub, entry) + if slave_count: + self._count = self._count * slave_count self._coordinator: DataUpdateCoordinator[list[int] | None] | None = None self._attr_native_unit_of_measurement = entry.get(CONF_UNIT_OF_MEASUREMENT) self._attr_state_class = entry.get(CONF_STATE_CLASS) From c9f474a4174ea3c0b3427c83226ea415bf220dce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 6 Aug 2023 12:20:28 -1000 Subject: [PATCH 057/120] Bump pyatv to 0.13.4 (#97932) --- homeassistant/components/apple_tv/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/apple_tv/manifest.json b/homeassistant/components/apple_tv/manifest.json index 1d1c26b5fcd..a22687c0fb5 100644 --- a/homeassistant/components/apple_tv/manifest.json +++ b/homeassistant/components/apple_tv/manifest.json @@ -7,7 +7,7 @@ "documentation": "https://www.home-assistant.io/integrations/apple_tv", "iot_class": "local_push", "loggers": ["pyatv", "srptools"], - "requirements": ["pyatv==0.13.3"], + "requirements": ["pyatv==0.13.4"], "zeroconf": [ "_mediaremotetv._tcp.local.", "_companion-link._tcp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index b44914a9596..a3bb9274cb4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1572,7 +1572,7 @@ pyatag==0.3.5.3 pyatmo==7.5.0 # homeassistant.components.apple_tv -pyatv==0.13.3 +pyatv==0.13.4 # homeassistant.components.aussie_broadband pyaussiebb==0.0.15 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 79edfa25e46..eb438270438 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1178,7 +1178,7 @@ pyatag==0.3.5.3 pyatmo==7.5.0 # homeassistant.components.apple_tv -pyatv==0.13.3 +pyatv==0.13.4 # homeassistant.components.aussie_broadband pyaussiebb==0.0.15 From 4b09e3b4a3eae91d41efbd31345d95f66abf8177 Mon Sep 17 00:00:00 2001 From: Alex Yao <33379584+alexyao2015@users.noreply.github.com> Date: Sun, 6 Aug 2023 17:20:48 -0500 Subject: [PATCH 058/120] Bump yeelight to v0.7.13 (#97933) Co-authored-by: alexyao2015 --- homeassistant/components/yeelight/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/yeelight/manifest.json b/homeassistant/components/yeelight/manifest.json index 7f5a67f4220..766ac0700e5 100644 --- a/homeassistant/components/yeelight/manifest.json +++ b/homeassistant/components/yeelight/manifest.json @@ -17,7 +17,7 @@ "iot_class": "local_push", "loggers": ["async_upnp_client", "yeelight"], "quality_scale": "platinum", - "requirements": ["yeelight==0.7.12", "async-upnp-client==0.34.1"], + "requirements": ["yeelight==0.7.13", "async-upnp-client==0.34.1"], "zeroconf": [ { "type": "_miio._udp.local.", diff --git a/requirements_all.txt b/requirements_all.txt index a3bb9274cb4..b6ff3bccf88 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2725,7 +2725,7 @@ yalexs-ble==2.2.3 yalexs==1.5.1 # homeassistant.components.yeelight -yeelight==0.7.12 +yeelight==0.7.13 # homeassistant.components.yeelightsunflower yeelightsunflower==0.0.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index eb438270438..a51db0bb880 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2007,7 +2007,7 @@ yalexs-ble==2.2.3 yalexs==1.5.1 # homeassistant.components.yeelight -yeelight==0.7.12 +yeelight==0.7.13 # homeassistant.components.yolink yolink-api==0.3.0 From 504d1643497c131a821b653f89da8a94740300ba Mon Sep 17 00:00:00 2001 From: tronikos Date: Mon, 7 Aug 2023 05:01:35 -0700 Subject: [PATCH 059/120] Android TV Remote: Fix missing key and cert when adding a device via IP address (#97953) Fix missing key and cert --- homeassistant/components/androidtv_remote/config_flow.py | 1 + tests/components/androidtv_remote/test_config_flow.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/homeassistant/components/androidtv_remote/config_flow.py b/homeassistant/components/androidtv_remote/config_flow.py index b8399fd7ba2..d5c361674bd 100644 --- a/homeassistant/components/androidtv_remote/config_flow.py +++ b/homeassistant/components/androidtv_remote/config_flow.py @@ -58,6 +58,7 @@ class AndroidTVRemoteConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): assert self.host api = create_api(self.hass, self.host, enable_ime=False) try: + await api.async_generate_cert_if_missing() self.name, self.mac = await api.async_get_name_and_mac() assert self.mac await self.async_set_unique_id(format_mac(self.mac)) diff --git a/tests/components/androidtv_remote/test_config_flow.py b/tests/components/androidtv_remote/test_config_flow.py index 4e0067152e7..a2792efb0f3 100644 --- a/tests/components/androidtv_remote/test_config_flow.py +++ b/tests/components/androidtv_remote/test_config_flow.py @@ -90,6 +90,7 @@ async def test_user_flow_cannot_connect( host = "1.2.3.4" + mock_api.async_generate_cert_if_missing = AsyncMock(return_value=True) mock_api.async_get_name_and_mac = AsyncMock(side_effect=CannotConnect()) result = await hass.config_entries.flow.async_configure( @@ -101,6 +102,7 @@ async def test_user_flow_cannot_connect( assert "host" in result["data_schema"].schema assert result["errors"] == {"base": "cannot_connect"} + mock_api.async_generate_cert_if_missing.assert_called() mock_api.async_get_name_and_mac.assert_called() mock_api.async_start_pairing.assert_not_called() @@ -329,6 +331,7 @@ async def test_user_flow_already_configured_host_changed_reloads_entry( assert "host" in result["data_schema"].schema assert not result["errors"] + mock_api.async_generate_cert_if_missing = AsyncMock(return_value=True) mock_api.async_get_name_and_mac = AsyncMock(return_value=(name, mac)) result = await hass.config_entries.flow.async_configure( @@ -338,6 +341,7 @@ async def test_user_flow_already_configured_host_changed_reloads_entry( assert result.get("type") == FlowResultType.ABORT assert result.get("reason") == "already_configured" + mock_api.async_generate_cert_if_missing.assert_called() mock_api.async_get_name_and_mac.assert_called() mock_api.async_start_pairing.assert_not_called() @@ -386,6 +390,7 @@ async def test_user_flow_already_configured_host_not_changed_no_reload_entry( assert "host" in result["data_schema"].schema assert not result["errors"] + mock_api.async_generate_cert_if_missing = AsyncMock(return_value=True) mock_api.async_get_name_and_mac = AsyncMock(return_value=(name, mac)) result = await hass.config_entries.flow.async_configure( @@ -395,6 +400,7 @@ async def test_user_flow_already_configured_host_not_changed_no_reload_entry( assert result.get("type") == FlowResultType.ABORT assert result.get("reason") == "already_configured" + mock_api.async_generate_cert_if_missing.assert_called() mock_api.async_get_name_and_mac.assert_called() mock_api.async_start_pairing.assert_not_called() From a2227079e47fe4c4d3b26b9985715c1ab9f94c12 Mon Sep 17 00:00:00 2001 From: lymanepp <4195527+lymanepp@users.noreply.github.com> Date: Mon, 7 Aug 2023 11:54:06 -0400 Subject: [PATCH 060/120] Fix tomorrowio integration for new users (#97973) The tomorrow.io integration isn't working for new users due to changes made by tomorrow.io. This fixes that with the following changes: * Add 60 minute timestep option * Change default timestep to 60 minutes --- homeassistant/components/tomorrowio/config_flow.py | 2 +- homeassistant/components/tomorrowio/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tomorrowio/config_flow.py b/homeassistant/components/tomorrowio/config_flow.py index cdb0032431c..d6855f42c0a 100644 --- a/homeassistant/components/tomorrowio/config_flow.py +++ b/homeassistant/components/tomorrowio/config_flow.py @@ -102,7 +102,7 @@ class TomorrowioOptionsConfigFlow(config_entries.OptionsFlow): vol.Required( CONF_TIMESTEP, default=self._config_entry.options[CONF_TIMESTEP], - ): vol.In([1, 5, 15, 30]), + ): vol.In([1, 5, 15, 30, 60]), } return self.async_show_form( diff --git a/homeassistant/components/tomorrowio/const.py b/homeassistant/components/tomorrowio/const.py index 51d8d5f31cc..7ad6ea60836 100644 --- a/homeassistant/components/tomorrowio/const.py +++ b/homeassistant/components/tomorrowio/const.py @@ -25,7 +25,7 @@ LOGGER = logging.getLogger(__package__) CONF_TIMESTEP = "timestep" FORECAST_TYPES = [DAILY, HOURLY, NOWCAST] -DEFAULT_TIMESTEP = 15 +DEFAULT_TIMESTEP = 60 DEFAULT_FORECAST_TYPE = DAILY DOMAIN = "tomorrowio" INTEGRATION_NAME = "Tomorrow.io" From 955c1ec2156c6dc2c9624821b48bf4fe94b6e139 Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Mon, 7 Aug 2023 18:14:47 -0400 Subject: [PATCH 061/120] Bump ZHA dependency bellows to 0.35.9 (#97976) Bump bellows to 0.35.8 --- homeassistant/components/zha/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 041a93a8ead..29fed3a3c9f 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -20,7 +20,7 @@ "zigpy_znp" ], "requirements": [ - "bellows==0.35.8", + "bellows==0.35.9", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.102", diff --git a/requirements_all.txt b/requirements_all.txt index b6ff3bccf88..8ccd8cf6c29 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -500,7 +500,7 @@ beautifulsoup4==4.11.1 # beewi-smartclim==0.0.10 # homeassistant.components.zha -bellows==0.35.8 +bellows==0.35.9 # homeassistant.components.bmw_connected_drive bimmer-connected==0.13.9 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a51db0bb880..f6b2e6cb305 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -424,7 +424,7 @@ base36==0.1.1 beautifulsoup4==4.11.1 # homeassistant.components.zha -bellows==0.35.8 +bellows==0.35.9 # homeassistant.components.bmw_connected_drive bimmer-connected==0.13.9 From 21f0210abd36c7b8737532d74e8f09b1472a29a2 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Mon, 7 Aug 2023 16:23:27 -0600 Subject: [PATCH 062/120] Bump `pyairvisual` to 2023.08.1 (#97999) --- homeassistant/components/airvisual/manifest.json | 2 +- homeassistant/components/airvisual_pro/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/airvisual/manifest.json b/homeassistant/components/airvisual/manifest.json index f7f509e2593..7934d809287 100644 --- a/homeassistant/components/airvisual/manifest.json +++ b/homeassistant/components/airvisual/manifest.json @@ -8,5 +8,5 @@ "integration_type": "service", "iot_class": "cloud_polling", "loggers": ["pyairvisual", "pysmb"], - "requirements": ["pyairvisual==2022.12.1"] + "requirements": ["pyairvisual==2023.08.1"] } diff --git a/homeassistant/components/airvisual_pro/manifest.json b/homeassistant/components/airvisual_pro/manifest.json index 0859754ba18..32dbc23a421 100644 --- a/homeassistant/components/airvisual_pro/manifest.json +++ b/homeassistant/components/airvisual_pro/manifest.json @@ -7,5 +7,5 @@ "integration_type": "device", "iot_class": "local_polling", "loggers": ["pyairvisual", "pysmb"], - "requirements": ["pyairvisual==2022.12.1"] + "requirements": ["pyairvisual==2023.08.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8ccd8cf6c29..246b042006e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1563,7 +1563,7 @@ pyairnow==1.2.1 # homeassistant.components.airvisual # homeassistant.components.airvisual_pro -pyairvisual==2022.12.1 +pyairvisual==2023.08.1 # homeassistant.components.atag pyatag==0.3.5.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f6b2e6cb305..08246c01efe 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1169,7 +1169,7 @@ pyairnow==1.2.1 # homeassistant.components.airvisual # homeassistant.components.airvisual_pro -pyairvisual==2022.12.1 +pyairvisual==2023.08.1 # homeassistant.components.atag pyatag==0.3.5.3 From dbbe1456a4334467d5d2bef83f74bcfca3885fa6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 7 Aug 2023 14:30:47 -1000 Subject: [PATCH 063/120] Bump aiohomekit to 2.6.15 (#98005) changelog: https://github.com/Jc2k/aiohomekit/compare/2.6.14...2.6.15 --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index d26b15bdc7a..52a91d42e67 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.14"], + "requirements": ["aiohomekit==2.6.15"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 246b042006e..b06d7db916f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -249,7 +249,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.14 +aiohomekit==2.6.15 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 08246c01efe..ce6c391d328 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -227,7 +227,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.14 +aiohomekit==2.6.15 # homeassistant.components.emulated_hue # homeassistant.components.http From 4e6c83906539c207ecc455c7c68bfa203530544c Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 8 Aug 2023 18:02:47 +0200 Subject: [PATCH 064/120] Add translation keys to Tuya cover (#98040) --- homeassistant/components/tuya/cover.py | 5 +++++ homeassistant/components/tuya/strings.json | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/homeassistant/components/tuya/cover.py b/homeassistant/components/tuya/cover.py index 3505bbf9f22..da9f7d29eb2 100644 --- a/homeassistant/components/tuya/cover.py +++ b/homeassistant/components/tuya/cover.py @@ -44,6 +44,7 @@ COVERS: dict[str, tuple[TuyaCoverEntityDescription, ...]] = { "cl": ( TuyaCoverEntityDescription( key=DPCode.CONTROL, + translation_key="curtain", current_state=DPCode.SITUATION_SET, current_position=(DPCode.PERCENT_CONTROL, DPCode.PERCENT_STATE), set_position=DPCode.PERCENT_CONTROL, @@ -65,6 +66,7 @@ COVERS: dict[str, tuple[TuyaCoverEntityDescription, ...]] = { ), TuyaCoverEntityDescription( key=DPCode.MACH_OPERATE, + translation_key="curtain", current_position=DPCode.POSITION, set_position=DPCode.POSITION, device_class=CoverDeviceClass.CURTAIN, @@ -76,6 +78,7 @@ COVERS: dict[str, tuple[TuyaCoverEntityDescription, ...]] = { # It is used by the Kogan Smart Blinds Driver TuyaCoverEntityDescription( key=DPCode.SWITCH_1, + translation_key="blind", current_position=DPCode.PERCENT_CONTROL, set_position=DPCode.PERCENT_CONTROL, device_class=CoverDeviceClass.BLIND, @@ -111,6 +114,7 @@ COVERS: dict[str, tuple[TuyaCoverEntityDescription, ...]] = { "clkg": ( TuyaCoverEntityDescription( key=DPCode.CONTROL, + translation_key="curtain", current_position=DPCode.PERCENT_CONTROL, set_position=DPCode.PERCENT_CONTROL, device_class=CoverDeviceClass.CURTAIN, @@ -128,6 +132,7 @@ COVERS: dict[str, tuple[TuyaCoverEntityDescription, ...]] = { "jdcljqr": ( TuyaCoverEntityDescription( key=DPCode.CONTROL, + translation_key="curtain", current_position=DPCode.PERCENT_STATE, set_position=DPCode.PERCENT_CONTROL, device_class=CoverDeviceClass.CURTAIN, diff --git a/homeassistant/components/tuya/strings.json b/homeassistant/components/tuya/strings.json index db16015ba56..1ea58f5029f 100644 --- a/homeassistant/components/tuya/strings.json +++ b/homeassistant/components/tuya/strings.json @@ -71,6 +71,12 @@ } }, "cover": { + "blind": { + "name": "[%key:component::cover::entity_component::blind::name%]" + }, + "curtain": { + "name": "[%key:component::cover::entity_component::curtain::name%]" + }, "curtain_2": { "name": "Curtain 2" }, From 73f0ac054217205dc3d8be0d6b00d69d9284452e Mon Sep 17 00:00:00 2001 From: Sam Reed Date: Tue, 8 Aug 2023 18:07:17 +0100 Subject: [PATCH 065/120] Remove trailing . from melcloud service descriptions (#98053) --- homeassistant/components/melcloud/strings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/melcloud/strings.json b/homeassistant/components/melcloud/strings.json index bef65e28880..e5447952c5e 100644 --- a/homeassistant/components/melcloud/strings.json +++ b/homeassistant/components/melcloud/strings.json @@ -26,7 +26,7 @@ "fields": { "position": { "name": "Position", - "description": "Horizontal vane position. Possible options can be found in the vane_horizontal_positions state attribute.\n." + "description": "Horizontal vane position. Possible options can be found in the vane_horizontal_positions state attribute." } } }, @@ -36,7 +36,7 @@ "fields": { "position": { "name": "Position", - "description": "Vertical vane position. Possible options can be found in the vane_vertical_positions state attribute.\n." + "description": "Vertical vane position. Possible options can be found in the vane_vertical_positions state attribute." } } } From 61cafb26ac4dd1d2509a570fbcfdb5ca9264c8f7 Mon Sep 17 00:00:00 2001 From: mkmer Date: Tue, 8 Aug 2023 13:39:26 -0400 Subject: [PATCH 066/120] Bump AIOAladdinConnect to 0.1.57 (#98056) --- homeassistant/components/aladdin_connect/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/aladdin_connect/manifest.json b/homeassistant/components/aladdin_connect/manifest.json index 2702f2e8dec..3f31a833f1a 100644 --- a/homeassistant/components/aladdin_connect/manifest.json +++ b/homeassistant/components/aladdin_connect/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/aladdin_connect", "iot_class": "cloud_polling", "loggers": ["aladdin_connect"], - "requirements": ["AIOAladdinConnect==0.1.56"] + "requirements": ["AIOAladdinConnect==0.1.57"] } diff --git a/requirements_all.txt b/requirements_all.txt index b06d7db916f..1362df5646d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -5,7 +5,7 @@ AEMET-OpenData==0.2.2 # homeassistant.components.aladdin_connect -AIOAladdinConnect==0.1.56 +AIOAladdinConnect==0.1.57 # homeassistant.components.honeywell AIOSomecomfort==0.0.15 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ce6c391d328..1bbdaae6548 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -7,7 +7,7 @@ AEMET-OpenData==0.2.2 # homeassistant.components.aladdin_connect -AIOAladdinConnect==0.1.56 +AIOAladdinConnect==0.1.57 # homeassistant.components.honeywell AIOSomecomfort==0.0.15 From 8bdac8fb30aeabe728296870aee8ed8d7159fcdf Mon Sep 17 00:00:00 2001 From: Maximilian <43999966+DeerMaximum@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:54:19 +0000 Subject: [PATCH 067/120] Bump pynina to 0.3.2 (#98070) --- homeassistant/components/nina/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/nina/manifest.json b/homeassistant/components/nina/manifest.json index d1897b53e04..df09d168827 100644 --- a/homeassistant/components/nina/manifest.json +++ b/homeassistant/components/nina/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/nina", "iot_class": "cloud_polling", "loggers": ["pynina"], - "requirements": ["PyNINA==0.3.1"] + "requirements": ["PyNINA==0.3.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index 1362df5646d..9c3b8353bc9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -79,7 +79,7 @@ PyMetno==0.10.0 PyMicroBot==0.0.9 # homeassistant.components.nina -PyNINA==0.3.1 +PyNINA==0.3.2 # homeassistant.components.mobile_app # homeassistant.components.owntracks diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1bbdaae6548..4aa8b3dc62b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -69,7 +69,7 @@ PyMetno==0.10.0 PyMicroBot==0.0.9 # homeassistant.components.nina -PyNINA==0.3.1 +PyNINA==0.3.2 # homeassistant.components.mobile_app # homeassistant.components.owntracks From a2637ac75a6930dd2918e4a69ba94df835d0327c Mon Sep 17 00:00:00 2001 From: tronikos Date: Wed, 9 Aug 2023 01:32:00 -0700 Subject: [PATCH 068/120] Bump opower to 0.0.24 (#98091) --- 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 94758720722..523cbe1d988 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.20"] + "requirements": ["opower==0.0.24"] } diff --git a/requirements_all.txt b/requirements_all.txt index 9c3b8353bc9..26cddca65c8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.20 +opower==0.0.24 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4aa8b3dc62b..dc408f5c9ee 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.20 +opower==0.0.24 # homeassistant.components.oralb oralb-ble==0.17.6 From 84d185a075055bf5c9c0ce5b2a9d3a5cc9a34cd0 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 11 Aug 2023 14:11:06 +0200 Subject: [PATCH 069/120] Improve UniFi control PoE mode (#98119) --- homeassistant/components/unifi/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/unifi/manifest.json b/homeassistant/components/unifi/manifest.json index 4cc45ddb6b8..3b1fa68638b 100644 --- a/homeassistant/components/unifi/manifest.json +++ b/homeassistant/components/unifi/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_push", "loggers": ["aiounifi"], "quality_scale": "platinum", - "requirements": ["aiounifi==51"], + "requirements": ["aiounifi==52"], "ssdp": [ { "manufacturer": "Ubiquiti Networks", diff --git a/requirements_all.txt b/requirements_all.txt index 26cddca65c8..264fad5cb87 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -360,7 +360,7 @@ aiosyncthing==0.5.1 aiotractive==0.5.5 # homeassistant.components.unifi -aiounifi==51 +aiounifi==52 # homeassistant.components.vlc_telnet aiovlc==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index dc408f5c9ee..c2b65ec0903 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -335,7 +335,7 @@ aiosyncthing==0.5.1 aiotractive==0.5.5 # homeassistant.components.unifi -aiounifi==51 +aiounifi==52 # homeassistant.components.vlc_telnet aiovlc==0.1.0 From d488bb3dca2997ff1ce1fef05d24c7203c2becd7 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 10 Aug 2023 18:04:24 +0200 Subject: [PATCH 070/120] Add missing translation key in Tuya (#98122) --- homeassistant/components/tuya/switch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tuya/switch.py b/homeassistant/components/tuya/switch.py index 676991fe167..a48d797555c 100644 --- a/homeassistant/components/tuya/switch.py +++ b/homeassistant/components/tuya/switch.py @@ -105,11 +105,11 @@ SWITCHES: dict[str, tuple[SwitchEntityDescription, ...]] = { translation_key="plug", ), ), - # Cirquit Breaker + # Circuit Breaker "dlq": ( SwitchEntityDescription( key=DPCode.CHILD_LOCK, - translation_key="asd", + translation_key="child_lock", icon="mdi:account-lock", entity_category=EntityCategory.CONFIG, ), From b584eb757bb758a450b888469ac5b75a9a215a9d Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 10 Aug 2023 12:37:28 +0200 Subject: [PATCH 071/120] Correct unit of rain pause (#98131) --- homeassistant/components/gardena_bluetooth/number.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/gardena_bluetooth/number.py b/homeassistant/components/gardena_bluetooth/number.py index c425d17621d..ec887458586 100644 --- a/homeassistant/components/gardena_bluetooth/number.py +++ b/homeassistant/components/gardena_bluetooth/number.py @@ -62,11 +62,11 @@ DESCRIPTIONS = ( GardenaBluetoothNumberEntityDescription( key=DeviceConfiguration.rain_pause.uuid, translation_key="rain_pause", - native_unit_of_measurement=UnitOfTime.DAYS, + native_unit_of_measurement=UnitOfTime.MINUTES, mode=NumberMode.BOX, native_min_value=0.0, - native_max_value=127.0, - native_step=1.0, + native_max_value=7 * 24 * 60, + native_step=6 * 60.0, entity_category=EntityCategory.CONFIG, char=DeviceConfiguration.rain_pause, ), From 32d4c2607bd5752e417d09265d4e4d3e894bcd2e Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Fri, 11 Aug 2023 13:07:45 +0200 Subject: [PATCH 072/120] Make gardena closing sensor unavailable when closed (#98133) --- homeassistant/components/gardena_bluetooth/sensor.py | 5 +++++ .../components/gardena_bluetooth/snapshots/test_sensor.ambr | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/gardena_bluetooth/sensor.py b/homeassistant/components/gardena_bluetooth/sensor.py index eaa44d9d4fb..ebc83ae88af 100644 --- a/homeassistant/components/gardena_bluetooth/sensor.py +++ b/homeassistant/components/gardena_bluetooth/sensor.py @@ -117,3 +117,8 @@ class GardenaBluetoothRemainSensor(GardenaBluetoothEntity, SensorEntity): self._attr_native_value = time super()._handle_coordinator_update() return + + @property + def available(self) -> bool: + """Sensor only available when open.""" + return super().available and self._attr_native_value is not None diff --git a/tests/components/gardena_bluetooth/snapshots/test_sensor.ambr b/tests/components/gardena_bluetooth/snapshots/test_sensor.ambr index 14135cb390c..8df37b40abc 100644 --- a/tests/components/gardena_bluetooth/snapshots/test_sensor.ambr +++ b/tests/components/gardena_bluetooth/snapshots/test_sensor.ambr @@ -35,7 +35,7 @@ 'entity_id': 'sensor.mock_title_valve_closing', 'last_changed': , 'last_updated': , - 'state': 'unknown', + 'state': 'unavailable', }) # --- # name: test_setup[98bd2a19-0b0e-421a-84e5-ddbf75dc6de4-raw0-sensor.mock_title_battery] From a2dec234c2496f1db090c393dee71b735ba10db3 Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 10 Aug 2023 02:13:55 -0700 Subject: [PATCH 073/120] Bump opower to 0.0.26 (#98141) --- 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 523cbe1d988..73942231b40 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.24"] + "requirements": ["opower==0.0.26"] } diff --git a/requirements_all.txt b/requirements_all.txt index 264fad5cb87..f8b99c108ee 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.24 +opower==0.0.26 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c2b65ec0903..ae430fe6959 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.24 +opower==0.0.26 # homeassistant.components.oralb oralb-ble==0.17.6 From 1ffbc8118db7155a3ce799810ab427eaf396b21a Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 10 Aug 2023 07:49:23 -0700 Subject: [PATCH 074/120] Opower: Add gas sensors for utilities that report CCF (#98142) Add gas sensors for utilities that report CCF --- homeassistant/components/opower/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/opower/sensor.py b/homeassistant/components/opower/sensor.py index 36f88a36e8a..ad94d8cafb6 100644 --- a/homeassistant/components/opower/sensor.py +++ b/homeassistant/components/opower/sensor.py @@ -188,7 +188,7 @@ async def async_setup_entry( sensors = ELEC_SENSORS elif ( forecast.account.meter_type == MeterType.GAS - and forecast.unit_of_measure == UnitOfMeasure.THERM + and forecast.unit_of_measure in [UnitOfMeasure.THERM, UnitOfMeasure.CCF] ): sensors = GAS_SENSORS for sensor in sensors: From 773ec3adb6116382447705fd79ad60d7ed008747 Mon Sep 17 00:00:00 2001 From: tronikos Date: Thu, 10 Aug 2023 03:11:01 -0700 Subject: [PATCH 075/120] Get Opower accounts from the customer endpoint (#98144) Get accounts from the customer endpoint --- homeassistant/components/opower/coordinator.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/opower/coordinator.py b/homeassistant/components/opower/coordinator.py index c331f45bc49..b346df1211c 100644 --- a/homeassistant/components/opower/coordinator.py +++ b/homeassistant/components/opower/coordinator.py @@ -69,12 +69,12 @@ class OpowerCoordinator(DataUpdateCoordinator[dict[str, Forecast]]): raise ConfigEntryAuthFailed from err forecasts: list[Forecast] = await self.api.async_get_forecast() _LOGGER.debug("Updating sensor data with: %s", forecasts) - await self._insert_statistics([forecast.account for forecast in forecasts]) + await self._insert_statistics() return {forecast.account.utility_account_id: forecast for forecast in forecasts} - async def _insert_statistics(self, accounts: list[Account]) -> None: + async def _insert_statistics(self) -> None: """Insert Opower statistics.""" - for account in accounts: + for account in await self.api.async_get_accounts(): id_prefix = "_".join( ( self.api.utility.subdomain(), From 819cea0ea0054b32bea7983e808ac2b975646da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Thu, 10 Aug 2023 16:47:16 +0200 Subject: [PATCH 076/120] Update aioairzone to v0.6.5 (#98163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Álvaro Fernández Rojas --- .../components/airzone/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/airzone/test_climate.py | 49 ++++++++++++++++++- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/airzone/manifest.json b/homeassistant/components/airzone/manifest.json index 88b918f699c..39adf08236e 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.6.4"] + "requirements": ["aioairzone==0.6.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index f8b99c108ee..f05751f0633 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -191,7 +191,7 @@ aioairq==0.2.4 aioairzone-cloud==0.2.1 # homeassistant.components.airzone -aioairzone==0.6.4 +aioairzone==0.6.5 # homeassistant.components.ambient_station aioambient==2023.04.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ae430fe6959..28d96d4f97d 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -172,7 +172,7 @@ aioairq==0.2.4 aioairzone-cloud==0.2.1 # homeassistant.components.airzone -aioairzone==0.6.4 +aioairzone==0.6.5 # homeassistant.components.ambient_station aioambient==2023.04.0 diff --git a/tests/components/airzone/test_climate.py b/tests/components/airzone/test_climate.py index f7cc7806bcb..3e68c056566 100644 --- a/tests/components/airzone/test_climate.py +++ b/tests/components/airzone/test_climate.py @@ -329,7 +329,7 @@ async def test_airzone_climate_set_hvac_mode(hass: HomeAssistant) -> None: await async_init_integration(hass) - HVAC_MOCK = { + HVAC_MOCK_1 = { API_DATA: [ { API_SYSTEM_ID: 1, @@ -340,7 +340,7 @@ async def test_airzone_climate_set_hvac_mode(hass: HomeAssistant) -> None: } with patch( "homeassistant.components.airzone.AirzoneLocalApi.put_hvac", - return_value=HVAC_MOCK, + return_value=HVAC_MOCK_1, ): await hass.services.async_call( CLIMATE_DOMAIN, @@ -407,6 +407,51 @@ async def test_airzone_climate_set_hvac_mode(hass: HomeAssistant) -> None: state = hass.states.get("climate.airzone_2_1") assert state.state == HVACMode.HEAT_COOL + HVAC_MOCK_4 = { + API_DATA: [ + { + API_SYSTEM_ID: 1, + API_ZONE_ID: 1, + API_ON: 1, + } + ] + } + with patch( + "homeassistant.components.airzone.AirzoneLocalApi.put_hvac", + return_value=HVAC_MOCK_4, + ): + await hass.services.async_call( + CLIMATE_DOMAIN, + SERVICE_SET_HVAC_MODE, + { + ATTR_ENTITY_ID: "climate.salon", + ATTR_HVAC_MODE: HVACMode.FAN_ONLY, + }, + blocking=True, + ) + + state = hass.states.get("climate.salon") + assert state.state == HVACMode.FAN_ONLY + + HVAC_MOCK_NO_SET_POINT = {**HVAC_MOCK} + del HVAC_MOCK_NO_SET_POINT[API_SYSTEMS][0][API_DATA][0][API_SET_POINT] + + with patch( + "homeassistant.components.airzone.AirzoneLocalApi.get_hvac", + return_value=HVAC_MOCK_NO_SET_POINT, + ), patch( + "homeassistant.components.airzone.AirzoneLocalApi.get_hvac_systems", + return_value=HVAC_SYSTEMS_MOCK, + ), patch( + "homeassistant.components.airzone.AirzoneLocalApi.get_webserver", + return_value=HVAC_WEBSERVER_MOCK, + ): + async_fire_time_changed(hass, utcnow() + SCAN_INTERVAL) + await hass.async_block_till_done() + + state = hass.states.get("climate.salon") + assert state.attributes.get(ATTR_TEMPERATURE) == 19.1 + async def test_airzone_climate_set_hvac_slave_error(hass: HomeAssistant) -> None: """Test setting the HVAC mode for a slave zone.""" From 63b2fa6d1b10f27951a1d5226dbd1e60b303df16 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 11 Aug 2023 12:15:04 +0200 Subject: [PATCH 077/120] Use explicit device name in Broadlink (#98229) --- homeassistant/components/broadlink/light.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/broadlink/light.py b/homeassistant/components/broadlink/light.py index d42e2b76b99..796698c6a4c 100644 --- a/homeassistant/components/broadlink/light.py +++ b/homeassistant/components/broadlink/light.py @@ -45,6 +45,7 @@ class BroadlinkLight(BroadlinkEntity, LightEntity): """Representation of a Broadlink light.""" _attr_has_entity_name = True + _attr_name = None def __init__(self, device): """Initialize the light.""" From 0ce00500680e04d043fdc1eee76a6d56c391488a Mon Sep 17 00:00:00 2001 From: MatthewFlamm <39341281+MatthewFlamm@users.noreply.github.com> Date: Fri, 11 Aug 2023 02:19:06 -0400 Subject: [PATCH 078/120] Bump pynws 1.5.1; fix regression for precipitation probability (#98237) bump pynws 1.5.1 --- homeassistant/components/nws/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/nws/manifest.json b/homeassistant/components/nws/manifest.json index 7f5d01f9897..05194d85a26 100644 --- a/homeassistant/components/nws/manifest.json +++ b/homeassistant/components/nws/manifest.json @@ -7,5 +7,5 @@ "iot_class": "cloud_polling", "loggers": ["metar", "pynws"], "quality_scale": "platinum", - "requirements": ["pynws==1.5.0"] + "requirements": ["pynws==1.5.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index f05751f0633..a0ec3b986cb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1872,7 +1872,7 @@ pynuki==1.6.2 pynut2==2.1.2 # homeassistant.components.nws -pynws==1.5.0 +pynws==1.5.1 # homeassistant.components.nx584 pynx584==0.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 28d96d4f97d..19fd1e51f0e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1388,7 +1388,7 @@ pynuki==1.6.2 pynut2==2.1.2 # homeassistant.components.nws -pynws==1.5.0 +pynws==1.5.1 # homeassistant.components.nx584 pynx584==0.5 From c72a1849239763bdcdf2c658bf3cd4d10ae5d88c Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 11 Aug 2023 14:20:04 +0200 Subject: [PATCH 079/120] Bumped version to 2023.8.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 0568650deb5..bcc9586e54b 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 8 -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, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index fdcd2788b58..0710b813402 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.8.1" +version = "2023.8.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From f641c0ba584e21222b72b0b12722aac313419bd7 Mon Sep 17 00:00:00 2001 From: Brandon Rothweiler <2292715+bdr99@users.noreply.github.com> Date: Wed, 9 Aug 2023 02:17:17 -0400 Subject: [PATCH 080/120] Bump pymazda to 0.3.11 (#98084) --- homeassistant/components/mazda/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/mazda/manifest.json b/homeassistant/components/mazda/manifest.json index dd29d02d655..881120a0677 100644 --- a/homeassistant/components/mazda/manifest.json +++ b/homeassistant/components/mazda/manifest.json @@ -7,5 +7,5 @@ "iot_class": "cloud_polling", "loggers": ["pymazda"], "quality_scale": "platinum", - "requirements": ["pymazda==0.3.10"] + "requirements": ["pymazda==0.3.11"] } diff --git a/requirements_all.txt b/requirements_all.txt index a0ec3b986cb..c0a87e85810 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1824,7 +1824,7 @@ pymailgunner==1.4 pymata-express==1.19 # homeassistant.components.mazda -pymazda==0.3.10 +pymazda==0.3.11 # homeassistant.components.mediaroom pymediaroom==0.6.5.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 19fd1e51f0e..a9cedeabbac 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1352,7 +1352,7 @@ pymailgunner==1.4 pymata-express==1.19 # homeassistant.components.mazda -pymazda==0.3.10 +pymazda==0.3.11 # homeassistant.components.melcloud pymelcloud==2.5.8 From 350e5ee9a7a5a4dbd21905b6b8b39e7d217c1533 Mon Sep 17 00:00:00 2001 From: Nick Whyte Date: Wed, 16 Aug 2023 21:56:52 +1000 Subject: [PATCH 081/120] Fix ness alarm armed_home state appearing as disarmed/armed_away (#94351) * Fix nessclient arm home appearing as arm away * patch arming mode enum and use dynamic access * Revert "patch arming mode enum and use dynamic access" This reverts commit b9cca8e92bcb382abe364381a8cb1674c32d1d2a. * Remove mock enums --- .../components/ness_alarm/__init__.py | 8 ++-- .../ness_alarm/alarm_control_panel.py | 22 ++++++++-- .../components/ness_alarm/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/ness_alarm/test_init.py | 44 +++++++------------ 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/homeassistant/components/ness_alarm/__init__.py b/homeassistant/components/ness_alarm/__init__.py index c1d97f781af..b5d30219550 100644 --- a/homeassistant/components/ness_alarm/__init__.py +++ b/homeassistant/components/ness_alarm/__init__.py @@ -3,7 +3,7 @@ from collections import namedtuple import datetime import logging -from nessclient import ArmingState, Client +from nessclient import ArmingMode, ArmingState, Client import voluptuous as vol from homeassistant.components.binary_sensor import ( @@ -136,9 +136,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: hass, SIGNAL_ZONE_CHANGED, ZoneChangedData(zone_id=zone_id, state=state) ) - def on_state_change(arming_state: ArmingState): + def on_state_change(arming_state: ArmingState, arming_mode: ArmingMode | None): """Receives and propagates arming state updates.""" - async_dispatcher_send(hass, SIGNAL_ARMING_STATE_CHANGED, arming_state) + async_dispatcher_send( + hass, SIGNAL_ARMING_STATE_CHANGED, arming_state, arming_mode + ) client.on_zone_change(on_zone_change) client.on_state_change(on_state_change) diff --git a/homeassistant/components/ness_alarm/alarm_control_panel.py b/homeassistant/components/ness_alarm/alarm_control_panel.py index 2f54b3abde6..92feaba13aa 100644 --- a/homeassistant/components/ness_alarm/alarm_control_panel.py +++ b/homeassistant/components/ness_alarm/alarm_control_panel.py @@ -3,12 +3,15 @@ from __future__ import annotations import logging -from nessclient import ArmingState, Client +from nessclient import ArmingMode, ArmingState, Client import homeassistant.components.alarm_control_panel as alarm from homeassistant.components.alarm_control_panel import AlarmControlPanelEntityFeature from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_ARMED_VACATION, STATE_ALARM_ARMING, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, @@ -23,6 +26,15 @@ from . import DATA_NESS, SIGNAL_ARMING_STATE_CHANGED _LOGGER = logging.getLogger(__name__) +ARMING_MODE_TO_STATE = { + ArmingMode.ARMED_AWAY: STATE_ALARM_ARMED_AWAY, + ArmingMode.ARMED_HOME: STATE_ALARM_ARMED_HOME, + ArmingMode.ARMED_DAY: STATE_ALARM_ARMED_AWAY, # no applicable state, fallback to away + ArmingMode.ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT, + ArmingMode.ARMED_VACATION: STATE_ALARM_ARMED_VACATION, + ArmingMode.ARMED_HIGHEST: STATE_ALARM_ARMED_AWAY, # no applicable state, fallback to away +} + async def async_setup_platform( hass: HomeAssistant, @@ -79,7 +91,9 @@ class NessAlarmPanel(alarm.AlarmControlPanelEntity): await self._client.panic(code) @callback - def _handle_arming_state_change(self, arming_state: ArmingState) -> None: + def _handle_arming_state_change( + self, arming_state: ArmingState, arming_mode: ArmingMode | None + ) -> None: """Handle arming state update.""" if arming_state == ArmingState.UNKNOWN: @@ -91,7 +105,9 @@ class NessAlarmPanel(alarm.AlarmControlPanelEntity): elif arming_state == ArmingState.EXIT_DELAY: self._attr_state = STATE_ALARM_ARMING elif arming_state == ArmingState.ARMED: - self._attr_state = STATE_ALARM_ARMED_AWAY + self._attr_state = ARMING_MODE_TO_STATE.get( + arming_mode, STATE_ALARM_ARMED_AWAY + ) elif arming_state == ArmingState.ENTRY_DELAY: self._attr_state = STATE_ALARM_PENDING elif arming_state == ArmingState.TRIGGERED: diff --git a/homeassistant/components/ness_alarm/manifest.json b/homeassistant/components/ness_alarm/manifest.json index d92a3d02c7a..e4c5b5fb344 100644 --- a/homeassistant/components/ness_alarm/manifest.json +++ b/homeassistant/components/ness_alarm/manifest.json @@ -5,5 +5,5 @@ "documentation": "https://www.home-assistant.io/integrations/ness_alarm", "iot_class": "local_push", "loggers": ["nessclient"], - "requirements": ["nessclient==0.10.0"] + "requirements": ["nessclient==1.0.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index c0a87e85810..6f31913f5d2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1243,7 +1243,7 @@ nad-receiver==0.3.0 ndms2-client==0.1.2 # homeassistant.components.ness_alarm -nessclient==0.10.0 +nessclient==1.0.0 # homeassistant.components.netdata netdata==1.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a9cedeabbac..475d7921357 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -957,7 +957,7 @@ mutesync==0.0.1 ndms2-client==0.1.2 # homeassistant.components.ness_alarm -nessclient==0.10.0 +nessclient==1.0.0 # homeassistant.components.nmap_tracker netmap==0.7.0.2 diff --git a/tests/components/ness_alarm/test_init.py b/tests/components/ness_alarm/test_init.py index 908e23ec795..5bf48e0667e 100644 --- a/tests/components/ness_alarm/test_init.py +++ b/tests/components/ness_alarm/test_init.py @@ -1,7 +1,7 @@ """Tests for the ness_alarm component.""" -from enum import Enum from unittest.mock import MagicMock, patch +from nessclient import ArmingMode, ArmingState import pytest from homeassistant.components import alarm_control_panel @@ -24,6 +24,8 @@ from homeassistant.const import ( SERVICE_ALARM_DISARM, SERVICE_ALARM_TRIGGER, STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_NIGHT, STATE_ALARM_ARMING, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, @@ -84,7 +86,7 @@ async def test_dispatch_state_change(hass: HomeAssistant, mock_nessclient) -> No await hass.async_block_till_done() on_state_change = mock_nessclient.on_state_change.call_args[0][0] - on_state_change(MockArmingState.ARMING) + on_state_change(ArmingState.ARMING, None) await hass.async_block_till_done() assert hass.states.is_state("alarm_control_panel.alarm_panel", STATE_ALARM_ARMING) @@ -174,13 +176,16 @@ async def test_dispatch_zone_change(hass: HomeAssistant, mock_nessclient) -> Non async def test_arming_state_change(hass: HomeAssistant, mock_nessclient) -> None: """Test arming state change handing.""" states = [ - (MockArmingState.UNKNOWN, STATE_UNKNOWN), - (MockArmingState.DISARMED, STATE_ALARM_DISARMED), - (MockArmingState.ARMING, STATE_ALARM_ARMING), - (MockArmingState.EXIT_DELAY, STATE_ALARM_ARMING), - (MockArmingState.ARMED, STATE_ALARM_ARMED_AWAY), - (MockArmingState.ENTRY_DELAY, STATE_ALARM_PENDING), - (MockArmingState.TRIGGERED, STATE_ALARM_TRIGGERED), + (ArmingState.UNKNOWN, None, STATE_UNKNOWN), + (ArmingState.DISARMED, None, STATE_ALARM_DISARMED), + (ArmingState.ARMING, None, STATE_ALARM_ARMING), + (ArmingState.EXIT_DELAY, None, STATE_ALARM_ARMING), + (ArmingState.ARMED, None, STATE_ALARM_ARMED_AWAY), + (ArmingState.ARMED, ArmingMode.ARMED_AWAY, STATE_ALARM_ARMED_AWAY), + (ArmingState.ARMED, ArmingMode.ARMED_HOME, STATE_ALARM_ARMED_HOME), + (ArmingState.ARMED, ArmingMode.ARMED_NIGHT, STATE_ALARM_ARMED_NIGHT), + (ArmingState.ENTRY_DELAY, None, STATE_ALARM_PENDING), + (ArmingState.TRIGGERED, None, STATE_ALARM_TRIGGERED), ] await async_setup_component(hass, DOMAIN, VALID_CONFIG) @@ -188,24 +193,12 @@ async def test_arming_state_change(hass: HomeAssistant, mock_nessclient) -> None assert hass.states.is_state("alarm_control_panel.alarm_panel", STATE_UNKNOWN) on_state_change = mock_nessclient.on_state_change.call_args[0][0] - for arming_state, expected_state in states: - on_state_change(arming_state) + for arming_state, arming_mode, expected_state in states: + on_state_change(arming_state, arming_mode) await hass.async_block_till_done() assert hass.states.is_state("alarm_control_panel.alarm_panel", expected_state) -class MockArmingState(Enum): - """Mock nessclient.ArmingState enum.""" - - UNKNOWN = "UNKNOWN" - DISARMED = "DISARMED" - ARMING = "ARMING" - EXIT_DELAY = "EXIT_DELAY" - ARMED = "ARMED" - ENTRY_DELAY = "ENTRY_DELAY" - TRIGGERED = "TRIGGERED" - - class MockClient: """Mock nessclient.Client stub.""" @@ -253,10 +246,5 @@ def mock_nessclient(): with patch( "homeassistant.components.ness_alarm.Client", new=_mock_factory, create=True - ), patch( - "homeassistant.components.ness_alarm.ArmingState", new=MockArmingState - ), patch( - "homeassistant.components.ness_alarm.alarm_control_panel.ArmingState", - new=MockArmingState, ): yield _mock_instance From cf839d0ce4394db439eecc8c14fc32a33cbd88b1 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Aug 2023 10:55:39 +0200 Subject: [PATCH 082/120] Correct modbus config validator: slave/swap (#97798) --- homeassistant/components/modbus/validators.py | 71 +++++++++++-------- tests/components/modbus/test_init.py | 11 ++- tests/components/modbus/test_sensor.py | 2 +- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index a583b93ea80..a87f8b2367c 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -65,25 +65,14 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: name = config[CONF_NAME] structure = config.get(CONF_STRUCTURE) slave_count = config.get(CONF_SLAVE_COUNT, 0) + 1 - swap_type = config.get(CONF_SWAP) - if config[CONF_DATA_TYPE] != DataType.CUSTOM: - if structure: - error = f"{name} structure: cannot be mixed with {data_type}" + slave = config.get(CONF_SLAVE, 0) + swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE) + if config[CONF_DATA_TYPE] == DataType.CUSTOM: + if slave or slave_count > 1: + error = f"{name}: `{CONF_STRUCTURE}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" raise vol.Invalid(error) - if data_type not in DEFAULT_STRUCT_FORMAT: - error = f"Error in sensor {name}. data_type `{data_type}` not supported" - raise vol.Invalid(error) - - structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" - if CONF_COUNT not in config: - config[CONF_COUNT] = DEFAULT_STRUCT_FORMAT[data_type].register_count - if slave_count > 1: - structure = f">{slave_count}{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" - else: - structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" - else: - if slave_count > 1: - error = f"{name} structure: cannot be mixed with {CONF_SLAVE_COUNT}" + if swap_type != CONF_SWAP_NONE: + error = f"{name}: `{CONF_STRUCTURE}` illegal with `{CONF_SWAP}`" raise vol.Invalid(error) if not structure: error = ( @@ -102,19 +91,43 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: f"Structure request {size} bytes, " f"but {count} registers have a size of {bytecount} bytes" ) + return { + **config, + CONF_STRUCTURE: structure, + CONF_SWAP: swap_type, + } - if swap_type != CONF_SWAP_NONE: - if swap_type == CONF_SWAP_BYTE: - regs_needed = 1 - else: # CONF_SWAP_WORD_BYTE, CONF_SWAP_WORD - regs_needed = 2 - if count < regs_needed or (count % regs_needed) != 0: - raise vol.Invalid( - f"Error in sensor {name} swap({swap_type}) " - "not possible due to the registers " - f"count: {count}, needed: {regs_needed}" - ) + if structure: + error = f"{name} structure: cannot be mixed with {data_type}" + raise vol.Invalid(error) + if data_type not in DEFAULT_STRUCT_FORMAT: + error = f"Error in sensor {name}. data_type `{data_type}` not supported" + raise vol.Invalid(error) + if (slave or slave_count > 1) and data_type == DataType.STRING: + error = ( + f"{name}: `{data_type}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" + ) + raise vol.Invalid(error) + if CONF_COUNT not in config: + config[CONF_COUNT] = DEFAULT_STRUCT_FORMAT[data_type].register_count + if swap_type != CONF_SWAP_NONE: + if swap_type == CONF_SWAP_BYTE: + regs_needed = 1 + else: # CONF_SWAP_WORD_BYTE, CONF_SWAP_WORD + regs_needed = 2 + count = config[CONF_COUNT] + if count < regs_needed or (count % regs_needed) != 0: + raise vol.Invalid( + f"Error in sensor {name} swap({swap_type}) " + "not possible due to the registers " + f"count: {count}, needed: {regs_needed}" + ) + structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" + if slave_count > 1: + structure = f">{slave_count}{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" + else: + structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" return { **config, CONF_STRUCTURE: structure, diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index 2daf722bb05..19c6157133e 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -163,7 +163,6 @@ async def test_number_validator() -> None: CONF_COUNT: 2, CONF_DATA_TYPE: DataType.CUSTOM, CONF_STRUCTURE: ">i", - CONF_SWAP: CONF_SWAP_BYTE, }, ], ) @@ -221,6 +220,16 @@ async def test_ok_struct_validator(do_config) -> None: CONF_STRUCTURE: ">f", CONF_SLAVE_COUNT: 5, }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_DATA_TYPE: DataType.STRING, + CONF_SLAVE_COUNT: 2, + }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_DATA_TYPE: DataType.INT16, + CONF_SWAP: CONF_SWAP_WORD, + }, ], ) async def test_exception_struct_validator(do_config) -> None: diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index be9ea95d86a..2a230bb125a 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -243,7 +243,7 @@ async def test_config_sensor(hass: HomeAssistant, mock_modbus) -> None: }, ] }, - f"Error in sensor {TEST_ENTITY_NAME} swap(word) not possible due to the registers count: 1, needed: 2", + f"{TEST_ENTITY_NAME}: `structure` illegal with `swap`", ), ], ) From 2a0c121f65effd6dbd8af59954ce1a23af157d3d Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 11 Aug 2023 04:47:49 -0700 Subject: [PATCH 083/120] Fix Opower utilities that have different ReadResolution than previously assumed (#97823) --- .../components/opower/coordinator.py | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/opower/coordinator.py b/homeassistant/components/opower/coordinator.py index b346df1211c..4e2b68df579 100644 --- a/homeassistant/components/opower/coordinator.py +++ b/homeassistant/components/opower/coordinator.py @@ -12,6 +12,7 @@ from opower import ( InvalidAuth, MeterType, Opower, + ReadResolution, ) from homeassistant.components.recorder import get_instance @@ -177,44 +178,55 @@ class OpowerCoordinator(DataUpdateCoordinator[dict[str, Forecast]]): """Get all cost reads since account activation but at different resolutions depending on age. - month resolution for all years (since account activation) - - day resolution for past 3 years - - hour resolution for past 2 months, only for electricity, not gas + - day resolution for past 3 years (if account's read resolution supports it) + - hour resolution for past 2 months (if account's read resolution supports it) """ cost_reads = [] + start = None - end = datetime.now() - timedelta(days=3 * 365) + end = datetime.now() + if account.read_resolution != ReadResolution.BILLING: + end -= timedelta(days=3 * 365) cost_reads += await self.api.async_get_cost_reads( account, AggregateType.BILL, start, end ) + if account.read_resolution == ReadResolution.BILLING: + return cost_reads + start = end if not cost_reads else cost_reads[-1].end_time - end = ( - datetime.now() - timedelta(days=2 * 30) - if account.meter_type == MeterType.ELEC - else datetime.now() - ) + end = datetime.now() + if account.read_resolution != ReadResolution.DAY: + end -= timedelta(days=2 * 30) cost_reads += await self.api.async_get_cost_reads( account, AggregateType.DAY, start, end ) - if account.meter_type == MeterType.ELEC: - start = end if not cost_reads else cost_reads[-1].end_time - end = datetime.now() - cost_reads += await self.api.async_get_cost_reads( - account, AggregateType.HOUR, start, end - ) + if account.read_resolution == ReadResolution.DAY: + return cost_reads + + start = end if not cost_reads else cost_reads[-1].end_time + end = datetime.now() + cost_reads += await self.api.async_get_cost_reads( + account, AggregateType.HOUR, start, end + ) return cost_reads async def _async_get_recent_cost_reads( self, account: Account, last_stat_time: float ) -> list[CostRead]: - """Get cost reads within the past 30 days to allow corrections in data from utilities. - - Hourly for electricity, daily for gas. - """ + """Get cost reads within the past 30 days to allow corrections in data from utilities.""" + if account.read_resolution in [ + ReadResolution.HOUR, + ReadResolution.HALF_HOUR, + ReadResolution.QUARTER_HOUR, + ]: + aggregate_type = AggregateType.HOUR + elif account.read_resolution == ReadResolution.DAY: + aggregate_type = AggregateType.DAY + else: + aggregate_type = AggregateType.BILL return await self.api.async_get_cost_reads( account, - AggregateType.HOUR - if account.meter_type == MeterType.ELEC - else AggregateType.DAY, + aggregate_type, datetime.fromtimestamp(last_stat_time) - timedelta(days=30), datetime.now(), ) From 0daa9722175ecd9574b034f7dacab160c3bdd7c6 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Aug 2023 13:10:13 +0200 Subject: [PATCH 084/120] modbus config: count and slave_count can normally not be mixed. (#97902) --- homeassistant/components/modbus/validators.py | 21 ++++++++++++------- tests/components/modbus/test_init.py | 6 ++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index a87f8b2367c..44ad596b520 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -67,6 +67,17 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: slave_count = config.get(CONF_SLAVE_COUNT, 0) + 1 slave = config.get(CONF_SLAVE, 0) swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE) + if ( + slave_count > 1 + and count > 1 + and data_type not in (DataType.CUSTOM, DataType.STRING) + ): + error = f"{name} {CONF_COUNT} cannot be mixed with {data_type}" + raise vol.Invalid(error) + if config[CONF_DATA_TYPE] != DataType.CUSTOM: + if structure: + error = f"{name} structure: cannot be mixed with {data_type}" + if config[CONF_DATA_TYPE] == DataType.CUSTOM: if slave or slave_count > 1: error = f"{name}: `{CONF_STRUCTURE}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" @@ -96,17 +107,11 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: CONF_STRUCTURE: structure, CONF_SWAP: swap_type, } - - if structure: - error = f"{name} structure: cannot be mixed with {data_type}" - raise vol.Invalid(error) if data_type not in DEFAULT_STRUCT_FORMAT: error = f"Error in sensor {name}. data_type `{data_type}` not supported" raise vol.Invalid(error) - if (slave or slave_count > 1) and data_type == DataType.STRING: - error = ( - f"{name}: `{data_type}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" - ) + if slave_count > 1 and data_type == DataType.STRING: + error = f"{name}: `{data_type}` illegal with `{CONF_SLAVE_COUNT}`" raise vol.Invalid(error) if CONF_COUNT not in config: diff --git a/tests/components/modbus/test_init.py b/tests/components/modbus/test_init.py index 19c6157133e..908e7209fb9 100644 --- a/tests/components/modbus/test_init.py +++ b/tests/components/modbus/test_init.py @@ -230,6 +230,12 @@ async def test_ok_struct_validator(do_config) -> None: CONF_DATA_TYPE: DataType.INT16, CONF_SWAP: CONF_SWAP_WORD, }, + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_COUNT: 2, + CONF_SLAVE_COUNT: 2, + CONF_DATA_TYPE: DataType.INT32, + }, ], ) async def test_exception_struct_validator(do_config) -> None: From d842b2574aa973cb54707cd4ef94303901f70702 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Wed, 16 Aug 2023 13:24:41 +0200 Subject: [PATCH 085/120] Create abstraction for Generic YeeLight (#97939) * Create abstraction for Generic YeeLight * Update light.py --- homeassistant/components/yeelight/light.py | 24 ++++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/yeelight/light.py b/homeassistant/components/yeelight/light.py index f5f39e9997d..a442540109a 100644 --- a/homeassistant/components/yeelight/light.py +++ b/homeassistant/components/yeelight/light.py @@ -238,7 +238,7 @@ def _parse_custom_effects(effects_config) -> dict[str, dict[str, Any]]: def _async_cmd(func): """Define a wrapper to catch exceptions from the bulb.""" - async def _async_wrap(self: YeelightGenericLight, *args, **kwargs): + async def _async_wrap(self: YeelightBaseLight, *args, **kwargs): for attempts in range(2): try: _LOGGER.debug("Calling %s with %s %s", func, args, kwargs) @@ -403,8 +403,8 @@ def _async_setup_services(hass: HomeAssistant): ) -class YeelightGenericLight(YeelightEntity, LightEntity): - """Representation of a Yeelight generic light.""" +class YeelightBaseLight(YeelightEntity, LightEntity): + """Abstract Yeelight light.""" _attr_color_mode = ColorMode.BRIGHTNESS _attr_supported_color_modes = {ColorMode.BRIGHTNESS} @@ -861,7 +861,13 @@ class YeelightGenericLight(YeelightEntity, LightEntity): await self._bulb.async_set_scene(scene_class, *args) -class YeelightColorLightSupport(YeelightGenericLight): +class YeelightGenericLight(YeelightBaseLight): + """Representation of a generic Yeelight.""" + + _attr_name = None + + +class YeelightColorLightSupport(YeelightBaseLight): """Representation of a Color Yeelight light support.""" _attr_supported_color_modes = {ColorMode.COLOR_TEMP, ColorMode.HS, ColorMode.RGB} @@ -884,7 +890,7 @@ class YeelightColorLightSupport(YeelightGenericLight): return YEELIGHT_COLOR_EFFECT_LIST -class YeelightWhiteTempLightSupport(YeelightGenericLight): +class YeelightWhiteTempLightSupport(YeelightBaseLight): """Representation of a White temp Yeelight light.""" _attr_name = None @@ -904,7 +910,7 @@ class YeelightNightLightSupport: return PowerMode.NORMAL -class YeelightWithoutNightlightSwitchMixIn(YeelightGenericLight): +class YeelightWithoutNightlightSwitchMixIn(YeelightBaseLight): """A mix-in for yeelights without a nightlight switch.""" @property @@ -940,7 +946,7 @@ class YeelightColorLightWithoutNightlightSwitchLight( class YeelightColorLightWithNightlightSwitch( - YeelightNightLightSupport, YeelightColorLightSupport, YeelightGenericLight + YeelightNightLightSupport, YeelightColorLightSupport, YeelightBaseLight ): """Representation of a Yeelight with rgb support and nightlight. @@ -964,7 +970,7 @@ class YeelightWhiteTempWithoutNightlightSwitch( class YeelightWithNightLight( - YeelightNightLightSupport, YeelightWhiteTempLightSupport, YeelightGenericLight + YeelightNightLightSupport, YeelightWhiteTempLightSupport, YeelightBaseLight ): """Representation of a Yeelight with temp only support and nightlight. @@ -979,7 +985,7 @@ class YeelightWithNightLight( return super().is_on and not self.device.is_nightlight_enabled -class YeelightNightLightMode(YeelightGenericLight): +class YeelightNightLightMode(YeelightBaseLight): """Representation of a Yeelight when in nightlight mode.""" _attr_color_mode = ColorMode.BRIGHTNESS From 0070a5e83d49095919d30fcd74f588db0b61ffbc Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Aug 2023 13:23:04 +0200 Subject: [PATCH 086/120] modbus: Repair swap for slaves (#97960) --- .../components/modbus/base_platform.py | 19 +- homeassistant/components/modbus/climate.py | 2 +- homeassistant/components/modbus/sensor.py | 5 +- tests/components/modbus/test_sensor.py | 183 +++++++++++++++++- 4 files changed, 192 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/modbus/base_platform.py b/homeassistant/components/modbus/base_platform.py index 337919c81f7..bd21e12368e 100644 --- a/homeassistant/components/modbus/base_platform.py +++ b/homeassistant/components/modbus/base_platform.py @@ -48,10 +48,12 @@ from .const import ( CONF_MIN_VALUE, CONF_PRECISION, CONF_SCALE, + CONF_SLAVE_COUNT, CONF_STATE_OFF, CONF_STATE_ON, CONF_SWAP, CONF_SWAP_BYTE, + CONF_SWAP_NONE, CONF_SWAP_WORD, CONF_SWAP_WORD_BYTE, CONF_VERIFY, @@ -155,15 +157,25 @@ class BaseStructPlatform(BasePlatform, RestoreEntity): """Initialize the switch.""" super().__init__(hub, config) self._swap = config[CONF_SWAP] + if self._swap == CONF_SWAP_NONE: + self._swap = None self._data_type = config[CONF_DATA_TYPE] self._structure: str = config[CONF_STRUCTURE] self._precision = config[CONF_PRECISION] self._scale = config[CONF_SCALE] self._offset = config[CONF_OFFSET] - self._count = config[CONF_COUNT] + self._slave_count = config.get(CONF_SLAVE_COUNT, 0) + self._slave_size = self._count = config[CONF_COUNT] - def _swap_registers(self, registers: list[int]) -> list[int]: + def _swap_registers(self, registers: list[int], slave_count: int) -> list[int]: """Do swap as needed.""" + if slave_count: + swapped = [] + for i in range(0, self._slave_count + 1): + inx = i * self._slave_size + inx2 = inx + self._slave_size + swapped.extend(self._swap_registers(registers[inx:inx2], 0)) + return swapped if self._swap in (CONF_SWAP_BYTE, CONF_SWAP_WORD_BYTE): # convert [12][34] --> [21][43] for i, register in enumerate(registers): @@ -191,7 +203,8 @@ class BaseStructPlatform(BasePlatform, RestoreEntity): def unpack_structure_result(self, registers: list[int]) -> str | None: """Convert registers to proper result.""" - registers = self._swap_registers(registers) + if self._swap: + registers = self._swap_registers(registers, self._slave_count) byte_string = b"".join([x.to_bytes(2, byteorder="big") for x in registers]) if self._data_type == DataType.STRING: return byte_string.decode() diff --git a/homeassistant/components/modbus/climate.py b/homeassistant/components/modbus/climate.py index 0a8b8dabeeb..3e5155b574c 100644 --- a/homeassistant/components/modbus/climate.py +++ b/homeassistant/components/modbus/climate.py @@ -206,7 +206,7 @@ class ModbusThermostat(BaseStructPlatform, RestoreEntity, ClimateEntity): int.from_bytes(as_bytes[i : i + 2], "big") for i in range(0, len(as_bytes), 2) ] - registers = self._swap_registers(raw_regs) + registers = self._swap_registers(raw_regs, 0) if self._data_type in ( DataType.INT16, diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index a1c89677e4f..61230969443 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -132,10 +132,7 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity): self._coordinator.async_set_updated_data(None) else: self._attr_native_value = result - if self._attr_native_value is None: - self._attr_available = False - else: - self._attr_available = True + self._attr_available = self._attr_native_value is not None self._lazy_errors = self._lazy_error_count self.async_write_ha_state() diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index 2a230bb125a..e973f226913 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -603,9 +603,7 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: CONF_ADDRESS: 51, CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING, CONF_DATA_TYPE: DataType.UINT32, - CONF_SCALE: 1, - CONF_OFFSET: 0, - CONF_PRECISION: 0, + CONF_SCAN_INTERVAL: 1, }, ], }, @@ -677,17 +675,184 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: ) async def test_slave_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: """Run test for sensor.""" - assert hass.states.get(ENTITY_ID).state == expected[0] entity_registry = er.async_get(hass) - - for i in range(1, len(expected)): - entity_id = f"{SENSOR_DOMAIN}.{TEST_ENTITY_NAME}_{i}".replace(" ", "_") - assert hass.states.get(entity_id).state == expected[i] - unique_id = f"{SLAVE_UNIQUE_ID}_{i}" + for i in range(0, len(expected)): + entity_id = f"{SENSOR_DOMAIN}.{TEST_ENTITY_NAME}".replace(" ", "_") + unique_id = f"{SLAVE_UNIQUE_ID}" + if i: + entity_id = f"{entity_id}_{i}" + unique_id = f"{unique_id}_{i}" entry = entity_registry.async_get(entity_id) + state = hass.states.get(entity_id).state + assert state == expected[i] assert entry.unique_id == unique_id +@pytest.mark.parametrize( + "do_config", + [ + { + CONF_SENSORS: [ + { + CONF_NAME: TEST_ENTITY_NAME, + CONF_ADDRESS: 51, + CONF_INPUT_TYPE: CALL_TYPE_REGISTER_HOLDING, + CONF_SCAN_INTERVAL: 1, + }, + ], + }, + ], +) +@pytest.mark.parametrize( + ("config_addon", "register_words", "do_exception", "expected"), + [ + ( + { + CONF_SLAVE_COUNT: 0, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_SWAP: CONF_SWAP_BYTE, + CONF_DATA_TYPE: DataType.UINT16, + }, + [0x0102], + False, + [str(int(0x0201))], + ), + ( + { + CONF_SLAVE_COUNT: 0, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_SWAP: CONF_SWAP_WORD, + CONF_DATA_TYPE: DataType.UINT32, + }, + [0x0102, 0x0304], + False, + [str(int(0x03040102))], + ), + ( + { + CONF_SLAVE_COUNT: 0, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_SWAP: CONF_SWAP_WORD, + CONF_DATA_TYPE: DataType.UINT64, + }, + [0x0102, 0x0304, 0x0506, 0x0708], + False, + [str(int(0x0708050603040102))], + ), + ( + { + CONF_SLAVE_COUNT: 1, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT16, + CONF_SWAP: CONF_SWAP_BYTE, + }, + [0x0102, 0x0304], + False, + [str(int(0x0201)), str(int(0x0403))], + ), + ( + { + CONF_SLAVE_COUNT: 1, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT32, + CONF_SWAP: CONF_SWAP_WORD, + }, + [0x0102, 0x0304, 0x0506, 0x0708], + False, + [str(int(0x03040102)), str(int(0x07080506))], + ), + ( + { + CONF_SLAVE_COUNT: 1, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT64, + CONF_SWAP: CONF_SWAP_WORD, + }, + [0x0102, 0x0304, 0x0506, 0x0708, 0x0901, 0x0902, 0x0903, 0x0904], + False, + [str(int(0x0708050603040102)), str(int(0x0904090309020901))], + ), + ( + { + CONF_SLAVE_COUNT: 3, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT16, + CONF_SWAP: CONF_SWAP_BYTE, + }, + [0x0102, 0x0304, 0x0506, 0x0708], + False, + [str(int(0x0201)), str(int(0x0403)), str(int(0x0605)), str(int(0x0807))], + ), + ( + { + CONF_SLAVE_COUNT: 3, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT32, + CONF_SWAP: CONF_SWAP_WORD, + }, + [ + 0x0102, + 0x0304, + 0x0506, + 0x0708, + 0x090A, + 0x0B0C, + 0x0D0E, + 0x0F00, + ], + False, + [ + str(int(0x03040102)), + str(int(0x07080506)), + str(int(0x0B0C090A)), + str(int(0x0F000D0E)), + ], + ), + ( + { + CONF_SLAVE_COUNT: 3, + CONF_UNIQUE_ID: SLAVE_UNIQUE_ID, + CONF_DATA_TYPE: DataType.UINT64, + CONF_SWAP: CONF_SWAP_WORD, + }, + [ + 0x0601, + 0x0602, + 0x0603, + 0x0604, + 0x0701, + 0x0702, + 0x0703, + 0x0704, + 0x0801, + 0x0802, + 0x0803, + 0x0804, + 0x0901, + 0x0902, + 0x0903, + 0x0904, + ], + False, + [ + str(int(0x0604060306020601)), + str(int(0x0704070307020701)), + str(int(0x0804080308020801)), + str(int(0x0904090309020901)), + ], + ), + ], +) +async def test_slave_swap_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: + """Run test for sensor.""" + for i in range(0, len(expected)): + entity_id = f"{SENSOR_DOMAIN}.{TEST_ENTITY_NAME}".replace(" ", "_") + if i: + entity_id = f"{entity_id}_{i}" + state = hass.states.get(entity_id).state + assert state == expected[i] + + @pytest.mark.parametrize( "do_config", [ From 3da1a611c2ded4ad03282969810f856d85629f19 Mon Sep 17 00:00:00 2001 From: VidFerris <29590790+VidFerris@users.noreply.github.com> Date: Wed, 16 Aug 2023 20:57:16 +1000 Subject: [PATCH 087/120] Use Local Timezone for Withings Integration (#98137) --- homeassistant/components/withings/common.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/withings/common.py b/homeassistant/components/withings/common.py index 9282e3977c1..ef3b6456d20 100644 --- a/homeassistant/components/withings/common.py +++ b/homeassistant/components/withings/common.py @@ -438,22 +438,16 @@ class DataManager: async def async_get_sleep_summary(self) -> dict[Measurement, Any]: """Get the sleep summary data.""" _LOGGER.debug("Updating withing sleep summary") - now = dt_util.utcnow() + now = dt_util.now() yesterday = now - datetime.timedelta(days=1) - yesterday_noon = datetime.datetime( - yesterday.year, - yesterday.month, - yesterday.day, - 12, - 0, - 0, - 0, - datetime.UTC, + yesterday_noon = dt_util.start_of_local_day(yesterday) + datetime.timedelta( + hours=12 ) + yesterday_noon_utc = dt_util.as_utc(yesterday_noon) def get_sleep_summary() -> SleepGetSummaryResponse: return self._api.sleep_get_summary( - lastupdate=yesterday_noon, + lastupdate=yesterday_noon_utc, data_fields=[ GetSleepSummaryField.BREATHING_DISTURBANCES_INTENSITY, GetSleepSummaryField.DEEP_SLEEP_DURATION, From 16d2c8043777fea8db0ceac7f00c14b0d3a05a71 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sat, 12 Aug 2023 11:37:43 -0700 Subject: [PATCH 088/120] Bump pyrainbird to 4.0.0 (#98271) --- homeassistant/components/rainbird/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/rainbird/manifest.json b/homeassistant/components/rainbird/manifest.json index 986e89783d7..07a0bc0a5f6 100644 --- a/homeassistant/components/rainbird/manifest.json +++ b/homeassistant/components/rainbird/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/rainbird", "iot_class": "local_polling", "loggers": ["pyrainbird"], - "requirements": ["pyrainbird==3.0.0"] + "requirements": ["pyrainbird==4.0.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 6f31913f5d2..5cc39788e33 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1952,7 +1952,7 @@ pyqwikswitch==0.93 pyrail==0.0.3 # homeassistant.components.rainbird -pyrainbird==3.0.0 +pyrainbird==4.0.0 # homeassistant.components.recswitch pyrecswitch==1.0.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 475d7921357..f724938214e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1453,7 +1453,7 @@ pyps4-2ndscreen==1.3.1 pyqwikswitch==0.93 # homeassistant.components.rainbird -pyrainbird==3.0.0 +pyrainbird==4.0.0 # homeassistant.components.risco pyrisco==0.5.7 From 07bb0fc16a0d7f2e6d8d4c32dead9430d818d5d2 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 12 Aug 2023 12:31:14 -0400 Subject: [PATCH 089/120] Bump Python-Roborock to 0.32.3 (#98303) bump to 0.32.3 --- homeassistant/components/roborock/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roborock/manifest.json b/homeassistant/components/roborock/manifest.json index 05fff332c67..01548a6334c 100644 --- a/homeassistant/components/roborock/manifest.json +++ b/homeassistant/components/roborock/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/roborock", "iot_class": "local_polling", "loggers": ["roborock"], - "requirements": ["python-roborock==0.32.2"] + "requirements": ["python-roborock==0.32.3"] } diff --git a/requirements_all.txt b/requirements_all.txt index 5cc39788e33..bc5126e2115 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2150,7 +2150,7 @@ python-qbittorrent==0.4.3 python-ripple-api==0.0.3 # homeassistant.components.roborock -python-roborock==0.32.2 +python-roborock==0.32.3 # homeassistant.components.smarttub python-smarttub==0.0.33 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f724938214e..47847a71775 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1579,7 +1579,7 @@ python-picnic-api==1.1.0 python-qbittorrent==0.4.3 # homeassistant.components.roborock -python-roborock==0.32.2 +python-roborock==0.32.3 # homeassistant.components.smarttub python-smarttub==0.0.33 From 9f69ab16048b00080b427a732b1446748a33a9e7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 12 Aug 2023 20:10:36 -0500 Subject: [PATCH 090/120] Bump flux-led to 1.0.2 (#98312) changelog: https://github.com/Danielhiversen/flux_led/compare/1.0.1...1.0.2 fixes #98310 --- homeassistant/components/flux_led/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/flux_led/manifest.json b/homeassistant/components/flux_led/manifest.json index 689f984722d..d3274738f75 100644 --- a/homeassistant/components/flux_led/manifest.json +++ b/homeassistant/components/flux_led/manifest.json @@ -54,5 +54,5 @@ "iot_class": "local_push", "loggers": ["flux_led"], "quality_scale": "platinum", - "requirements": ["flux-led==1.0.1"] + "requirements": ["flux-led==1.0.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index bc5126e2115..d9174da9827 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -800,7 +800,7 @@ fjaraskupan==2.2.0 flipr-api==1.5.0 # homeassistant.components.flux_led -flux-led==1.0.1 +flux-led==1.0.2 # homeassistant.components.homekit # homeassistant.components.recorder diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 47847a71775..230286557e4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -628,7 +628,7 @@ fjaraskupan==2.2.0 flipr-api==1.5.0 # homeassistant.components.flux_led -flux-led==1.0.1 +flux-led==1.0.2 # homeassistant.components.homekit # homeassistant.components.recorder From 69c61a263246d2206863cf8d1af28f65d52c052f Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Mon, 14 Aug 2023 11:51:08 +0200 Subject: [PATCH 091/120] Use default translations by removing names from tplink descriptions (#98338) --- homeassistant/components/tplink/sensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/homeassistant/components/tplink/sensor.py b/homeassistant/components/tplink/sensor.py index ba4949434f7..46909f39dfe 100644 --- a/homeassistant/components/tplink/sensor.py +++ b/homeassistant/components/tplink/sensor.py @@ -50,7 +50,6 @@ ENERGY_SENSORS: tuple[TPLinkSensorEntityDescription, ...] = ( native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, - name="Current Consumption", emeter_attr="power", precision=1, ), @@ -60,7 +59,6 @@ ENERGY_SENSORS: tuple[TPLinkSensorEntityDescription, ...] = ( native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, - name="Total Consumption", emeter_attr="total", precision=3, ), @@ -70,7 +68,6 @@ ENERGY_SENSORS: tuple[TPLinkSensorEntityDescription, ...] = ( native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, - name="Today's Consumption", precision=3, ), TPLinkSensorEntityDescription( From a962d2b28d5e785f7538ec6569eeabf239ddb55f Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Mon, 14 Aug 2023 13:30:25 +0200 Subject: [PATCH 092/120] Fix tts notify config validation (#98381) * Add test * Require either entity_id or tts_service --- homeassistant/components/tts/notify.py | 23 +++++++++++++---------- tests/components/tts/test_notify.py | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/tts/notify.py b/homeassistant/components/tts/notify.py index 92244fc41f9..c2576e12bb5 100644 --- a/homeassistant/components/tts/notify.py +++ b/homeassistant/components/tts/notify.py @@ -20,16 +20,19 @@ ENTITY_LEGACY_PROVIDER_GROUP = "entity_or_legacy_provider" _LOGGER = logging.getLogger(__name__) -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Required(CONF_NAME): cv.string, - vol.Exclusive(CONF_TTS_SERVICE, ENTITY_LEGACY_PROVIDER_GROUP): cv.entity_id, - vol.Exclusive(CONF_ENTITY_ID, ENTITY_LEGACY_PROVIDER_GROUP): cv.entities_domain( - DOMAIN - ), - vol.Required(CONF_MEDIA_PLAYER): cv.entity_id, - vol.Optional(ATTR_LANGUAGE): cv.string, - } +PLATFORM_SCHEMA = vol.All( + cv.has_at_least_one_key(CONF_TTS_SERVICE, CONF_ENTITY_ID), + PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_NAME): cv.string, + vol.Exclusive(CONF_TTS_SERVICE, ENTITY_LEGACY_PROVIDER_GROUP): cv.entity_id, + vol.Exclusive( + CONF_ENTITY_ID, ENTITY_LEGACY_PROVIDER_GROUP + ): cv.entities_domain(DOMAIN), + vol.Required(CONF_MEDIA_PLAYER): cv.entity_id, + vol.Optional(ATTR_LANGUAGE): cv.string, + } + ), ) diff --git a/tests/components/tts/test_notify.py b/tests/components/tts/test_notify.py index 22ab151b864..1a776140457 100644 --- a/tests/components/tts/test_notify.py +++ b/tests/components/tts/test_notify.py @@ -68,6 +68,21 @@ async def test_setup_platform(hass: HomeAssistant) -> None: assert hass.services.has_service(notify.DOMAIN, "tts_test") +async def test_setup_platform_missing_key(hass: HomeAssistant) -> None: + """Test platform without required tts_service or entity_id key.""" + config = { + notify.DOMAIN: { + "platform": "tts", + "name": "tts_test", + "media_player": "media_player.demo", + } + } + with assert_setup_component(0, notify.DOMAIN): + assert await async_setup_component(hass, notify.DOMAIN, config) + + assert not hass.services.has_service(notify.DOMAIN, "tts_test") + + async def test_setup_legacy_service(hass: HomeAssistant) -> None: """Set up the demo platform and call service.""" calls = async_mock_service(hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) From b76a4e07875e82b6338af73feec409fd701ca101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Matheson=20Wergeland?= Date: Thu, 17 Aug 2023 15:12:35 +0200 Subject: [PATCH 093/120] Fix GoGoGate2 configuration URL when remote access is disabled (#98387) --- homeassistant/components/gogogate2/common.py | 7 ++++--- tests/components/gogogate2/__init__.py | 2 +- tests/components/gogogate2/test_cover.py | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/gogogate2/common.py b/homeassistant/components/gogogate2/common.py index d45a4fb44ec..a6b2f344ab3 100644 --- a/homeassistant/components/gogogate2/common.py +++ b/homeassistant/components/gogogate2/common.py @@ -113,9 +113,10 @@ class GoGoGate2Entity(CoordinatorEntity[DeviceDataUpdateCoordinator]): def device_info(self) -> DeviceInfo: """Device info for the controller.""" data = self.coordinator.data - configuration_url = ( - f"https://{data.remoteaccess}" if data.remoteaccess else None - ) + if data.remoteaccessenabled: + configuration_url = f"https://{data.remoteaccess}" + else: + configuration_url = f"http://{self._config_entry.data[CONF_IP_ADDRESS]}" return DeviceInfo( configuration_url=configuration_url, identifiers={(DOMAIN, str(self._config_entry.unique_id))}, diff --git a/tests/components/gogogate2/__init__.py b/tests/components/gogogate2/__init__.py index f7e3d40a44b..08675c58709 100644 --- a/tests/components/gogogate2/__init__.py +++ b/tests/components/gogogate2/__init__.py @@ -77,7 +77,7 @@ def _mocked_ismartgate_closed_door_response(): ismartgatename="ismartgatename0", model="ismartgatePRO", apiversion="", - remoteaccessenabled=False, + remoteaccessenabled=True, remoteaccess="abc321.blah.blah", firmwareversion="555", pin=123, diff --git a/tests/components/gogogate2/test_cover.py b/tests/components/gogogate2/test_cover.py index 00cc0057d7c..ca6509d53b9 100644 --- a/tests/components/gogogate2/test_cover.py +++ b/tests/components/gogogate2/test_cover.py @@ -340,6 +340,7 @@ async def test_device_info_ismartgate( assert device.name == "mycontroller" assert device.model == "ismartgatePRO" assert device.sw_version == "555" + assert device.configuration_url == "https://abc321.blah.blah" @patch("homeassistant.components.gogogate2.common.GogoGate2Api") @@ -375,3 +376,4 @@ async def test_device_info_gogogate2( assert device.name == "mycontroller" assert device.model == "gogogate2" assert device.sw_version == "222" + assert device.configuration_url == "http://127.0.0.1" From a66e30885780a9eac065060db65f3b49fa304793 Mon Sep 17 00:00:00 2001 From: mkmer Date: Wed, 16 Aug 2023 12:59:34 -0400 Subject: [PATCH 094/120] Handle missing keys in Honeywell (#98392) --- homeassistant/components/honeywell/climate.py | 6 +++--- homeassistant/components/honeywell/sensor.py | 3 ++- tests/components/honeywell/test_climate.py | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/honeywell/climate.py b/homeassistant/components/honeywell/climate.py index db31baa53a6..0168e4407f7 100644 --- a/homeassistant/components/honeywell/climate.py +++ b/homeassistant/components/honeywell/climate.py @@ -146,13 +146,13 @@ class HoneywellUSThermostat(ClimateEntity): | ClimateEntityFeature.TARGET_TEMPERATURE_RANGE ) - if device._data["canControlHumidification"]: + if device._data.get("canControlHumidification"): self._attr_supported_features |= ClimateEntityFeature.TARGET_HUMIDITY - if device.raw_ui_data["SwitchEmergencyHeatAllowed"]: + if device.raw_ui_data.get("SwitchEmergencyHeatAllowed"): self._attr_supported_features |= ClimateEntityFeature.AUX_HEAT - if not device._data["hasFan"]: + if not device._data.get("hasFan"): return # not all honeywell fans support all modes diff --git a/homeassistant/components/honeywell/sensor.py b/homeassistant/components/honeywell/sensor.py index ae4ede2a079..6a91e493488 100644 --- a/homeassistant/components/honeywell/sensor.py +++ b/homeassistant/components/honeywell/sensor.py @@ -20,6 +20,7 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType +from . import HoneywellData from .const import DOMAIN, HUMIDITY_STATUS_KEY, TEMPERATURE_STATUS_KEY @@ -71,7 +72,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Honeywell thermostat.""" - data = hass.data[DOMAIN][config_entry.entry_id] + data: HoneywellData = hass.data[DOMAIN][config_entry.entry_id] sensors = [] for device in data.devices.values(): diff --git a/tests/components/honeywell/test_climate.py b/tests/components/honeywell/test_climate.py index afb49cbffca..4d6989d79e8 100644 --- a/tests/components/honeywell/test_climate.py +++ b/tests/components/honeywell/test_climate.py @@ -48,13 +48,13 @@ FAN_ACTION = "fan_action" PRESET_HOLD = "Hold" -async def test_no_thermostats( +async def test_no_thermostat_options( hass: HomeAssistant, device: MagicMock, config_entry: MagicMock ) -> None: - """Test the setup of the climate entities when there are no appliances available.""" + """Test the setup of the climate entities when there are no additional options available.""" device._data = {} await init_integration(hass, config_entry) - assert len(hass.states.async_all()) == 0 + assert len(hass.states.async_all()) == 1 async def test_static_attributes( From 9bbf855a7d3f909bc70575c22f2238e2137b22aa Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Tue, 15 Aug 2023 10:43:19 +0200 Subject: [PATCH 095/120] Bump Reolink_aio to 0.7.7 (#98425) --- homeassistant/components/reolink/binary_sensor.py | 4 ++++ homeassistant/components/reolink/host.py | 2 +- homeassistant/components/reolink/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/reolink/binary_sensor.py b/homeassistant/components/reolink/binary_sensor.py index 850aa110171..996f2c6b3ab 100644 --- a/homeassistant/components/reolink/binary_sensor.py +++ b/homeassistant/components/reolink/binary_sensor.py @@ -5,6 +5,7 @@ from collections.abc import Callable from dataclasses import dataclass from reolink_aio.api import ( + DUAL_LENS_DUAL_MOTION_MODELS, FACE_DETECTION_TYPE, PERSON_DETECTION_TYPE, PET_DETECTION_TYPE, @@ -128,6 +129,9 @@ class ReolinkBinarySensorEntity(ReolinkChannelCoordinatorEntity, BinarySensorEnt super().__init__(reolink_data, channel) self.entity_description = entity_description + if self._host.api.model in DUAL_LENS_DUAL_MOTION_MODELS: + self._attr_name = f"{entity_description.name} lens {self._channel}" + self._attr_unique_id = ( f"{self._host.unique_id}_{self._channel}_{entity_description.key}" ) diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index 9bcafb8f00d..d505d92b8a9 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -163,7 +163,7 @@ class ReolinkHost: else: _LOGGER.debug( "Camera model %s most likely does not push its initial state" - "upon ONVIF subscription, do not check", + " upon ONVIF subscription, do not check", self._api.model, ) self._cancel_onvif_check = async_call_later( diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index fa61f873cca..f350bb4f948 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -18,5 +18,5 @@ "documentation": "https://www.home-assistant.io/integrations/reolink", "iot_class": "local_push", "loggers": ["reolink_aio"], - "requirements": ["reolink-aio==0.7.6"] + "requirements": ["reolink-aio==0.7.7"] } diff --git a/requirements_all.txt b/requirements_all.txt index d9174da9827..d5d67364c7d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2278,7 +2278,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.6 +reolink-aio==0.7.7 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 230286557e4..1c5737d40f2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1674,7 +1674,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.6 +reolink-aio==0.7.7 # homeassistant.components.rflink rflink==0.0.65 From d44d84b430034405954a7260e12c65aea3de2d15 Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Tue, 15 Aug 2023 03:02:38 -0500 Subject: [PATCH 096/120] Update rokuecp to 0.18.1 (#98432) --- homeassistant/components/roku/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/roku/manifest.json b/homeassistant/components/roku/manifest.json index f9b81dc8ddd..6fe70a3ab65 100644 --- a/homeassistant/components/roku/manifest.json +++ b/homeassistant/components/roku/manifest.json @@ -11,7 +11,7 @@ "iot_class": "local_polling", "loggers": ["rokuecp"], "quality_scale": "silver", - "requirements": ["rokuecp==0.18.0"], + "requirements": ["rokuecp==0.18.1"], "ssdp": [ { "st": "roku:ecp", diff --git a/requirements_all.txt b/requirements_all.txt index d5d67364c7d..092f90b5907 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2299,7 +2299,7 @@ rjpl==0.3.6 rocketchat-API==0.6.1 # homeassistant.components.roku -rokuecp==0.18.0 +rokuecp==0.18.1 # homeassistant.components.roomba roombapy==1.6.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1c5737d40f2..51ee7fd315e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1683,7 +1683,7 @@ rflink==0.0.65 ring-doorbell==0.7.2 # homeassistant.components.roku -rokuecp==0.18.0 +rokuecp==0.18.1 # homeassistant.components.roomba roombapy==1.6.8 From c55b96eb657c966560b84f5f55caec812762e3eb Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Tue, 15 Aug 2023 02:57:10 -0500 Subject: [PATCH 097/120] Update pyipp to 0.14.3 (#98434) --- homeassistant/components/ipp/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/ipp/manifest.json b/homeassistant/components/ipp/manifest.json index 7cdf6767362..e8bd4425ef3 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.14.2"], + "requirements": ["pyipp==0.14.3"], "zeroconf": ["_ipps._tcp.local.", "_ipp._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 092f90b5907..63e63a3492f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1746,7 +1746,7 @@ pyintesishome==1.8.0 pyipma==3.0.6 # homeassistant.components.ipp -pyipp==0.14.2 +pyipp==0.14.3 # homeassistant.components.iqvia pyiqvia==2022.04.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 51ee7fd315e..d4b24cb834a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1292,7 +1292,7 @@ pyinsteon==1.4.3 pyipma==3.0.6 # homeassistant.components.ipp -pyipp==0.14.2 +pyipp==0.14.3 # homeassistant.components.iqvia pyiqvia==2022.04.0 From 06d36983fe16961448487ac5d91894f8ce42a97e Mon Sep 17 00:00:00 2001 From: Luca Leonardo Scorcia Date: Fri, 18 Aug 2023 04:52:22 -0400 Subject: [PATCH 098/120] Fix inconsistent lyric temperature unit (#98457) --- homeassistant/components/lyric/climate.py | 22 +++++++++++++--------- homeassistant/components/lyric/sensor.py | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/lyric/climate.py b/homeassistant/components/lyric/climate.py index 099a0a028d0..df90ebcd6cf 100644 --- a/homeassistant/components/lyric/climate.py +++ b/homeassistant/components/lyric/climate.py @@ -21,7 +21,12 @@ from homeassistant.components.climate import ( HVACMode, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ATTR_TEMPERATURE +from homeassistant.const import ( + ATTR_TEMPERATURE, + PRECISION_HALVES, + PRECISION_WHOLE, + UnitOfTemperature, +) from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import entity_platform @@ -113,7 +118,6 @@ async def async_setup_entry( ), location, device, - hass.config.units.temperature_unit, ) ) @@ -140,10 +144,15 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): description: ClimateEntityDescription, location: LyricLocation, device: LyricDevice, - temperature_unit: str, ) -> None: """Initialize Honeywell Lyric climate entity.""" - self._temperature_unit = temperature_unit + # Use the native temperature unit from the device settings + if device.units == "Fahrenheit": + self._attr_temperature_unit = UnitOfTemperature.FAHRENHEIT + self._attr_precision = PRECISION_WHOLE + else: + self._attr_temperature_unit = UnitOfTemperature.CELSIUS + self._attr_precision = PRECISION_HALVES # Setup supported hvac modes self._attr_hvac_modes = [HVACMode.OFF] @@ -176,11 +185,6 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity): return SUPPORT_FLAGS_LCC return SUPPORT_FLAGS_TCC - @property - def temperature_unit(self) -> str: - """Return the unit of measurement.""" - return self._temperature_unit - @property def current_temperature(self) -> float | None: """Return the current temperature.""" diff --git a/homeassistant/components/lyric/sensor.py b/homeassistant/components/lyric/sensor.py index 1201a675a5d..1e15ff58b18 100644 --- a/homeassistant/components/lyric/sensor.py +++ b/homeassistant/components/lyric/sensor.py @@ -17,7 +17,7 @@ from homeassistant.components.sensor import ( SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import PERCENTAGE +from homeassistant.const import PERCENTAGE, UnitOfTemperature from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -76,6 +76,11 @@ async def async_setup_entry( for location in coordinator.data.locations: for device in location.devices: if device.indoorTemperature: + if device.units == "Fahrenheit": + native_temperature_unit = UnitOfTemperature.FAHRENHEIT + else: + native_temperature_unit = UnitOfTemperature.CELSIUS + entities.append( LyricSensor( coordinator, @@ -84,7 +89,7 @@ async def async_setup_entry( name="Indoor Temperature", device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=hass.config.units.temperature_unit, + native_unit_of_measurement=native_temperature_unit, value=lambda device: device.indoorTemperature, ), location, @@ -108,6 +113,11 @@ async def async_setup_entry( ) ) if device.outdoorTemperature: + if device.units == "Fahrenheit": + native_temperature_unit = UnitOfTemperature.FAHRENHEIT + else: + native_temperature_unit = UnitOfTemperature.CELSIUS + entities.append( LyricSensor( coordinator, @@ -116,7 +126,7 @@ async def async_setup_entry( name="Outdoor Temperature", device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=hass.config.units.temperature_unit, + native_unit_of_measurement=native_temperature_unit, value=lambda device: device.outdoorTemperature, ), location, From a835d07773c30b01629a30fad33e7809bdb499be Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 16 Aug 2023 04:30:47 -0500 Subject: [PATCH 099/120] Bump aiohomekit to 2.6.16 (#98490) --- homeassistant/components/homekit_controller/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index 52a91d42e67..5096544ba05 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -14,6 +14,6 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "iot_class": "local_push", "loggers": ["aiohomekit", "commentjson"], - "requirements": ["aiohomekit==2.6.15"], + "requirements": ["aiohomekit==2.6.16"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 63e63a3492f..5ce3056f8a0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -249,7 +249,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.15 +aiohomekit==2.6.16 # homeassistant.components.emulated_hue # homeassistant.components.http diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d4b24cb834a..1fb103c6123 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -227,7 +227,7 @@ aioguardian==2022.07.0 aioharmony==0.2.10 # homeassistant.components.homekit_controller -aiohomekit==2.6.15 +aiohomekit==2.6.16 # homeassistant.components.emulated_hue # homeassistant.components.http From c81c0149a2013777e1c3410ca1b429252e2a37d3 Mon Sep 17 00:00:00 2001 From: tronikos Date: Wed, 16 Aug 2023 02:10:02 -0700 Subject: [PATCH 100/120] Bump opower to 0.0.29 (#98503) --- 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 73942231b40..31929df5bf6 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.26"] + "requirements": ["opower==0.0.29"] } diff --git a/requirements_all.txt b/requirements_all.txt index 5ce3056f8a0..64625844828 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.26 +opower==0.0.29 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1fb103c6123..95ee58edde0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.26 +opower==0.0.29 # homeassistant.components.oralb oralb-ble==0.17.6 From aaefc29e32c69dfef49ad11420b5dd6ded2b97ae Mon Sep 17 00:00:00 2001 From: Erwin Douna Date: Thu, 17 Aug 2023 16:16:47 +0200 Subject: [PATCH 101/120] Revert "Integration tado bump" (#98505) Revert "Integration tado bump (#97791)" This reverts commit 65365d1db57a5e8cdf58d925c6e52871eb75f6be. --- homeassistant/components/tado/__init__.py | 39 +++++++++++---------- homeassistant/components/tado/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/tado/__init__.py b/homeassistant/components/tado/__init__.py index b57d384124c..1cd21634c8e 100644 --- a/homeassistant/components/tado/__init__.py +++ b/homeassistant/components/tado/__init__.py @@ -163,11 +163,12 @@ class TadoConnector: def setup(self): """Connect to Tado and fetch the zones.""" - self.tado = Tado(self._username, self._password, None, True) + self.tado = Tado(self._username, self._password) + self.tado.setDebugging(True) # Load zones and devices - self.zones = self.tado.get_zones() - self.devices = self.tado.get_devices() - tado_home = self.tado.get_me()["homes"][0] + self.zones = self.tado.getZones() + self.devices = self.tado.getDevices() + tado_home = self.tado.getMe()["homes"][0] self.home_id = tado_home["id"] self.home_name = tado_home["name"] @@ -180,7 +181,7 @@ class TadoConnector: def update_devices(self): """Update the device data from Tado.""" - devices = self.tado.get_devices() + devices = self.tado.getDevices() for device in devices: device_short_serial_no = device["shortSerialNo"] _LOGGER.debug("Updating device %s", device_short_serial_no) @@ -189,7 +190,7 @@ class TadoConnector: INSIDE_TEMPERATURE_MEASUREMENT in device["characteristics"]["capabilities"] ): - device[TEMP_OFFSET] = self.tado.get_device_info( + device[TEMP_OFFSET] = self.tado.getDeviceInfo( device_short_serial_no, TEMP_OFFSET ) except RuntimeError: @@ -217,7 +218,7 @@ class TadoConnector: def update_zones(self): """Update the zone data from Tado.""" try: - zone_states = self.tado.get_zone_states()["zoneStates"] + zone_states = self.tado.getZoneStates()["zoneStates"] except RuntimeError: _LOGGER.error("Unable to connect to Tado while updating zones") return @@ -229,7 +230,7 @@ class TadoConnector: """Update the internal data from Tado.""" _LOGGER.debug("Updating zone %s", zone_id) try: - data = self.tado.get_zone_state(zone_id) + data = self.tado.getZoneState(zone_id) except RuntimeError: _LOGGER.error("Unable to connect to Tado while updating zone %s", zone_id) return @@ -250,8 +251,8 @@ class TadoConnector: def update_home(self): """Update the home data from Tado.""" try: - self.data["weather"] = self.tado.get_weather() - self.data["geofence"] = self.tado.get_home_state() + self.data["weather"] = self.tado.getWeather() + self.data["geofence"] = self.tado.getHomeState() dispatcher_send( self.hass, SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "home", "data"), @@ -264,15 +265,15 @@ class TadoConnector: def get_capabilities(self, zone_id): """Return the capabilities of the devices.""" - return self.tado.get_capabilities(zone_id) + return self.tado.getCapabilities(zone_id) def get_auto_geofencing_supported(self): """Return whether the Tado Home supports auto geofencing.""" - return self.tado.get_auto_geofencing_supported() + return self.tado.getAutoGeofencingSupported() def reset_zone_overlay(self, zone_id): """Reset the zone back to the default operation.""" - self.tado.reset_zone_overlay(zone_id) + self.tado.resetZoneOverlay(zone_id) self.update_zone(zone_id) def set_presence( @@ -281,11 +282,11 @@ class TadoConnector: ): """Set the presence to home, away or auto.""" if presence == PRESET_AWAY: - self.tado.set_away() + self.tado.setAway() elif presence == PRESET_HOME: - self.tado.set_home() + self.tado.setHome() elif presence == PRESET_AUTO: - self.tado.set_auto() + self.tado.setAuto() # Update everything when changing modes self.update_zones() @@ -319,7 +320,7 @@ class TadoConnector: ) try: - self.tado.set_zone_overlay( + self.tado.setZoneOverlay( zone_id, overlay_mode, temperature, @@ -339,7 +340,7 @@ class TadoConnector: def set_zone_off(self, zone_id, overlay_mode, device_type="HEATING"): """Set a zone to off.""" try: - self.tado.set_zone_overlay( + self.tado.setZoneOverlay( zone_id, overlay_mode, None, None, device_type, "OFF" ) except RequestException as exc: @@ -350,6 +351,6 @@ class TadoConnector: def set_temperature_offset(self, device_id, offset): """Set temperature offset of device.""" try: - self.tado.set_temp_offset(device_id, offset) + self.tado.setTempOffset(device_id, offset) except RequestException as exc: _LOGGER.error("Could not set temperature offset: %s", exc) diff --git a/homeassistant/components/tado/manifest.json b/homeassistant/components/tado/manifest.json index bea608514bd..62f7a377239 100644 --- a/homeassistant/components/tado/manifest.json +++ b/homeassistant/components/tado/manifest.json @@ -14,5 +14,5 @@ }, "iot_class": "cloud_polling", "loggers": ["PyTado"], - "requirements": ["python-tado==0.16.0"] + "requirements": ["python-tado==0.15.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 64625844828..9c3faddfe6f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2159,7 +2159,7 @@ python-smarttub==0.0.33 python-songpal==0.15.2 # homeassistant.components.tado -python-tado==0.16.0 +python-tado==0.15.0 # homeassistant.components.telegram_bot python-telegram-bot==13.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 95ee58edde0..77696e217f0 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1588,7 +1588,7 @@ python-smarttub==0.0.33 python-songpal==0.15.2 # homeassistant.components.tado -python-tado==0.16.0 +python-tado==0.15.0 # homeassistant.components.telegram_bot python-telegram-bot==13.1 From 1c7e3005aa1f9b5e14560f20428212362f653823 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Fri, 18 Aug 2023 08:49:43 +0000 Subject: [PATCH 102/120] Fix the availability condition for Shelly N current sensor (#98518) --- homeassistant/components/shelly/sensor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/shelly/sensor.py b/homeassistant/components/shelly/sensor.py index b52e176b521..d1e05e5b829 100644 --- a/homeassistant/components/shelly/sensor.py +++ b/homeassistant/components/shelly/sensor.py @@ -533,7 +533,8 @@ RPC_SENSORS: Final = { native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, - available=lambda status: status["n_current"] is not None, + available=lambda status: (status and status["n_current"]) is not None, + removal_condition=lambda _config, status, _key: "n_current" not in status, entity_registry_enabled_default=False, ), "total_current": RpcSensorDescription( From 88352b6ca109d6db2d269afb43ab7f6e0960ad30 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Aug 2023 10:48:57 +0200 Subject: [PATCH 103/120] Correct number of registers to read for sensors for modbus (#98534) --- homeassistant/components/modbus/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/modbus/sensor.py b/homeassistant/components/modbus/sensor.py index 61230969443..76d8c4e0b5a 100644 --- a/homeassistant/components/modbus/sensor.py +++ b/homeassistant/components/modbus/sensor.py @@ -68,7 +68,7 @@ class ModbusRegisterSensor(BaseStructPlatform, RestoreSensor, SensorEntity): """Initialize the modbus register sensor.""" super().__init__(hub, entry) if slave_count: - self._count = self._count * slave_count + self._count = self._count * (slave_count + 1) self._coordinator: DataUpdateCoordinator[list[int] | None] | None = None self._attr_native_unit_of_measurement = entry.get(CONF_UNIT_OF_MEASUREMENT) self._attr_state_class = entry.get(CONF_STATE_CLASS) From 8dcb04eab1f16eee89ca5b94d2e6a92b8c203f3f Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 17 Aug 2023 17:36:22 +0200 Subject: [PATCH 104/120] Pin setuptools to 68.0.0 (#98582) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0710b813402..b486a7460f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools~=68.0", "wheel~=0.40.0"] +requires = ["setuptools==68.0.0", "wheel~=0.40.0"] build-backend = "setuptools.build_meta" [project] From 1c069539f578d0b39f750926c3c52ff75a63ca97 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 17 Aug 2023 10:39:35 -0500 Subject: [PATCH 105/120] Bump ESPHome recommended BLE version to 2023.8.0 (#98586) --- homeassistant/components/esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/esphome/const.py b/homeassistant/components/esphome/const.py index f0e3972f197..575c57c8672 100644 --- a/homeassistant/components/esphome/const.py +++ b/homeassistant/components/esphome/const.py @@ -11,7 +11,7 @@ DEFAULT_ALLOW_SERVICE_CALLS = True DEFAULT_NEW_CONFIG_ALLOW_ALLOW_SERVICE_CALLS = False -STABLE_BLE_VERSION_STR = "2023.6.0" +STABLE_BLE_VERSION_STR = "2023.8.0" STABLE_BLE_VERSION = AwesomeVersion(STABLE_BLE_VERSION_STR) PROJECT_URLS = { "esphome.bluetooth-proxy": "https://esphome.github.io/bluetooth-proxies/", From 7c5b1c8cd2d75c07374713dca9a85ddfcc76317e Mon Sep 17 00:00:00 2001 From: Niels Perfors Date: Fri, 18 Aug 2023 10:26:01 +0200 Subject: [PATCH 106/120] Verisure unpack (#98605) --- .../components/verisure/coordinator.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/verisure/coordinator.py b/homeassistant/components/verisure/coordinator.py index bc3b68922b0..bbfaed0a0a4 100644 --- a/homeassistant/components/verisure/coordinator.py +++ b/homeassistant/components/verisure/coordinator.py @@ -83,13 +83,16 @@ class VerisureDataUpdateCoordinator(DataUpdateCoordinator): raise UpdateFailed("Could not read overview") from err def unpack(overview: list, value: str) -> dict | list: - return next( - ( - item["data"]["installation"][value] - for item in overview - if value in item.get("data", {}).get("installation", {}) - ), - [], + return ( + next( + ( + item["data"]["installation"][value] + for item in overview + if value in item.get("data", {}).get("installation", {}) + ), + [], + ) + or [] ) # Store data in a way Home Assistant can easily consume it From 9291fab0b492cc536f0a1b433c20b36e0038a90f Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 18 Aug 2023 13:09:35 +0200 Subject: [PATCH 107/120] Update frontend to 20230802.1 (#98616) --- 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 84d1d4f5e27..986dfd6ba52 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==20230802.0"] + "requirements": ["home-assistant-frontend==20230802.1"] } diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index fa5b52478d0..d21007ae08b 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -22,7 +22,7 @@ ha-av==10.1.1 hass-nabucasa==0.69.0 hassil==1.2.5 home-assistant-bluetooth==1.10.2 -home-assistant-frontend==20230802.0 +home-assistant-frontend==20230802.1 home-assistant-intents==2023.8.2 httpx==0.24.1 ifaddr==0.2.0 diff --git a/requirements_all.txt b/requirements_all.txt index 9c3faddfe6f..a95ebbc09ed 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -988,7 +988,7 @@ hole==0.8.0 holidays==0.28 # homeassistant.components.frontend -home-assistant-frontend==20230802.0 +home-assistant-frontend==20230802.1 # homeassistant.components.conversation home-assistant-intents==2023.8.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 77696e217f0..0178acea600 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -774,7 +774,7 @@ hole==0.8.0 holidays==0.28 # homeassistant.components.frontend -home-assistant-frontend==20230802.0 +home-assistant-frontend==20230802.1 # homeassistant.components.conversation home-assistant-intents==2023.8.2 From ce0f957ce4c31ddc8847c9a16e9feaeefb856507 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 18 Aug 2023 13:56:56 +0200 Subject: [PATCH 108/120] Bumped version to 2023.8.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 bcc9586e54b..db28d072aa5 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 8 -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, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index b486a7460f7..d3e2f065e1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.8.2" +version = "2023.8.3" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" From bd0fe63dc83dab66dc183683a5ff9f4f0c710670 Mon Sep 17 00:00:00 2001 From: Markus Ressel Date: Mon, 21 Aug 2023 11:09:39 +0200 Subject: [PATCH 109/120] Fix octoprint down every two minutes (#90001) --- .../components/octoprint/__init__.py | 30 +++++++++++++------ .../components/octoprint/config_flow.py | 29 +++++++++++++----- .../components/octoprint/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/octoprint/__init__.py b/homeassistant/components/octoprint/__init__.py index dd6ab5794fc..790b332dbfd 100644 --- a/homeassistant/components/octoprint/__init__.py +++ b/homeassistant/components/octoprint/__init__.py @@ -5,6 +5,7 @@ from datetime import timedelta import logging from typing import cast +import aiohttp from pyoctoprintapi import ApiError, OctoprintClient, PrinterOffline from pyoctoprintapi.exceptions import UnauthorizedException import voluptuous as vol @@ -22,11 +23,11 @@ from homeassistant.const import ( CONF_SENSORS, CONF_SSL, CONF_VERIFY_SSL, + EVENT_HOMEASSISTANT_STOP, Platform, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryAuthFailed -from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.typing import ConfigType @@ -163,14 +164,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: data = {**entry.data, CONF_VERIFY_SSL: True} hass.config_entries.async_update_entry(entry, data=data) - verify_ssl = entry.data[CONF_VERIFY_SSL] - websession = async_get_clientsession(hass, verify_ssl=verify_ssl) + connector = aiohttp.TCPConnector( + force_close=True, + ssl=False if not entry.data[CONF_VERIFY_SSL] else None, + ) + session = aiohttp.ClientSession(connector=connector) + + @callback + def _async_close_websession(event: Event) -> None: + """Close websession.""" + session.detach() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_close_websession) + client = OctoprintClient( - entry.data[CONF_HOST], - websession, - entry.data[CONF_PORT], - entry.data[CONF_SSL], - entry.data[CONF_PATH], + host=entry.data[CONF_HOST], + session=session, + port=entry.data[CONF_PORT], + ssl=entry.data[CONF_SSL], + path=entry.data[CONF_PATH], ) client.set_api_key(entry.data[CONF_API_KEY]) diff --git a/homeassistant/components/octoprint/config_flow.py b/homeassistant/components/octoprint/config_flow.py index 33aaff8976e..09ac53ecf5b 100644 --- a/homeassistant/components/octoprint/config_flow.py +++ b/homeassistant/components/octoprint/config_flow.py @@ -6,6 +6,7 @@ from collections.abc import Mapping import logging from typing import Any +import aiohttp from pyoctoprintapi import ApiError, OctoprintClient, OctoprintException import voluptuous as vol from yarl import URL @@ -22,7 +23,6 @@ from homeassistant.const import ( CONF_VERIFY_SSL, ) from homeassistant.data_entry_flow import FlowResult -from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from .const import DOMAIN @@ -58,6 +58,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow for OctoPrint.""" self.discovery_schema = None self._user_input = None + self._sessions: list[aiohttp.ClientSession] = [] async def async_step_user(self, user_input=None): """Handle the initial step.""" @@ -260,14 +261,26 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): def _get_octoprint_client(self, user_input: dict) -> OctoprintClient: """Build an octoprint client from the user_input.""" verify_ssl = user_input.get(CONF_VERIFY_SSL, True) - session = async_get_clientsession(self.hass, verify_ssl=verify_ssl) - return OctoprintClient( - user_input[CONF_HOST], - session, - user_input[CONF_PORT], - user_input[CONF_SSL], - user_input[CONF_PATH], + + connector = aiohttp.TCPConnector( + force_close=True, + ssl=False if not verify_ssl else None, ) + session = aiohttp.ClientSession(connector=connector) + self._sessions.append(session) + + return OctoprintClient( + host=user_input[CONF_HOST], + session=session, + port=user_input[CONF_PORT], + ssl=user_input[CONF_SSL], + path=user_input[CONF_PATH], + ) + + def async_remove(self): + """Detach the session.""" + for session in self._sessions: + session.detach() class CannotConnect(exceptions.HomeAssistantError): diff --git a/homeassistant/components/octoprint/manifest.json b/homeassistant/components/octoprint/manifest.json index e4bc70e5d86..005cf5305d9 100644 --- a/homeassistant/components/octoprint/manifest.json +++ b/homeassistant/components/octoprint/manifest.json @@ -6,7 +6,7 @@ "documentation": "https://www.home-assistant.io/integrations/octoprint", "iot_class": "local_polling", "loggers": ["pyoctoprintapi"], - "requirements": ["pyoctoprintapi==0.1.11"], + "requirements": ["pyoctoprintapi==0.1.12"], "ssdp": [ { "manufacturer": "The OctoPrint Project", diff --git a/requirements_all.txt b/requirements_all.txt index a95ebbc09ed..8c2d87b5bfb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1884,7 +1884,7 @@ pynzbgetapi==0.2.0 pyobihai==1.4.2 # homeassistant.components.octoprint -pyoctoprintapi==0.1.11 +pyoctoprintapi==0.1.12 # homeassistant.components.ombi pyombi==0.1.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0178acea600..070ee5893fb 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1400,7 +1400,7 @@ pynzbgetapi==0.2.0 pyobihai==1.4.2 # homeassistant.components.octoprint -pyoctoprintapi==0.1.11 +pyoctoprintapi==0.1.12 # homeassistant.components.openuv pyopenuv==2023.02.0 From e1eb1cf2fbcb1d7ae34c56625d9f01b3c9b95bdb Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Aug 2023 23:18:55 +0200 Subject: [PATCH 110/120] modbus: slave is allowed with custom (#98644) --- homeassistant/components/modbus/validators.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index 44ad596b520..47ce518ec67 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -65,7 +65,6 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: name = config[CONF_NAME] structure = config.get(CONF_STRUCTURE) slave_count = config.get(CONF_SLAVE_COUNT, 0) + 1 - slave = config.get(CONF_SLAVE, 0) swap_type = config.get(CONF_SWAP, CONF_SWAP_NONE) if ( slave_count > 1 @@ -79,7 +78,7 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: error = f"{name} structure: cannot be mixed with {data_type}" if config[CONF_DATA_TYPE] == DataType.CUSTOM: - if slave or slave_count > 1: + if slave_count > 1: error = f"{name}: `{CONF_STRUCTURE}` illegal with `{CONF_SLAVE_COUNT}` / `{CONF_SLAVE}`" raise vol.Invalid(error) if swap_type != CONF_SWAP_NONE: From cdb088327ca48a28474e0d57c59fb9dd64faacaa Mon Sep 17 00:00:00 2001 From: tronikos Date: Fri, 18 Aug 2023 23:57:25 -0700 Subject: [PATCH 111/120] Bump opowerto 0.0.30 (#98660) --- 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 31929df5bf6..e7a76c63aaf 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.29"] + "requirements": ["opower==0.0.30"] } diff --git a/requirements_all.txt b/requirements_all.txt index 8c2d87b5bfb..4870f483455 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.29 +opower==0.0.30 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 070ee5893fb..b2579f1a2dc 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.29 +opower==0.0.30 # homeassistant.components.oralb oralb-ble==0.17.6 From ebdf48e41f4c23b5537cd2f965fa7fef0a51df88 Mon Sep 17 00:00:00 2001 From: jan iversen Date: Mon, 21 Aug 2023 22:55:50 +0200 Subject: [PATCH 112/120] Correct modbus swap/datatype error message (#98698) --- homeassistant/components/modbus/validators.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/modbus/validators.py b/homeassistant/components/modbus/validators.py index 47ce518ec67..4f3f4a1c8a1 100644 --- a/homeassistant/components/modbus/validators.py +++ b/homeassistant/components/modbus/validators.py @@ -124,8 +124,7 @@ def struct_validator(config: dict[str, Any]) -> dict[str, Any]: if count < regs_needed or (count % regs_needed) != 0: raise vol.Invalid( f"Error in sensor {name} swap({swap_type}) " - "not possible due to the registers " - f"count: {count}, needed: {regs_needed}" + f"impossible because datatype({data_type}) is too small" ) structure = f">{DEFAULT_STRUCT_FORMAT[data_type].struct_id}" if slave_count > 1: From dc6e752adfff88d8ddbcb3c6ea9f63ec50db3e91 Mon Sep 17 00:00:00 2001 From: tronikos Date: Sun, 20 Aug 2023 13:29:16 -0700 Subject: [PATCH 113/120] Bump opower to 0.0.31 (#98716) --- 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 e7a76c63aaf..2de5b268999 100644 --- a/homeassistant/components/opower/manifest.json +++ b/homeassistant/components/opower/manifest.json @@ -6,5 +6,5 @@ "dependencies": ["recorder"], "documentation": "https://www.home-assistant.io/integrations/opower", "iot_class": "cloud_polling", - "requirements": ["opower==0.0.30"] + "requirements": ["opower==0.0.31"] } diff --git a/requirements_all.txt b/requirements_all.txt index 4870f483455..5c267d9ee47 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1368,7 +1368,7 @@ openwrt-luci-rpc==1.1.16 openwrt-ubus-rpc==0.0.2 # homeassistant.components.opower -opower==0.0.30 +opower==0.0.31 # homeassistant.components.oralb oralb-ble==0.17.6 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b2579f1a2dc..72843065df4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1037,7 +1037,7 @@ openerz-api==0.2.0 openhomedevice==2.2.0 # homeassistant.components.opower -opower==0.0.30 +opower==0.0.31 # homeassistant.components.oralb oralb-ble==0.17.6 From ce8eebebc5f89f0cc6a5dd45b5edd5d7b74337f0 Mon Sep 17 00:00:00 2001 From: Florent Thiery Date: Mon, 21 Aug 2023 17:45:15 +0200 Subject: [PATCH 114/120] Reduce Freebox router Raid warning to one occurence (#98740) * consider Freebox router does not support Raid if the first enumeration raised an http error, fixes #98274 * add router name to warning message * reduce log level to info, remove details --- homeassistant/components/freebox/router.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index 122242f1959..f5aa51983c6 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -72,6 +72,7 @@ class FreeboxRouter: self.devices: dict[str, dict[str, Any]] = {} self.disks: dict[int, dict[str, Any]] = {} + self.supports_raid = True self.raids: dict[int, dict[str, Any]] = {} self.sensors_temperature: dict[str, int] = {} self.sensors_connection: dict[str, float] = {} @@ -160,14 +161,21 @@ class FreeboxRouter: async def _update_raids_sensors(self) -> None: """Update Freebox raids.""" - # None at first request + if not self.supports_raid: + return + try: fbx_raids: list[dict[str, Any]] = await self._api.storage.get_raids() or [] except HttpRequestError: - _LOGGER.warning("Unable to enumerate raid disks") - else: - for fbx_raid in fbx_raids: - self.raids[fbx_raid["id"]] = fbx_raid + self.supports_raid = False + _LOGGER.info( + "Router %s API does not support RAID", + self.name, + ) + return + + for fbx_raid in fbx_raids: + self.raids[fbx_raid["id"]] = fbx_raid async def update_home_devices(self) -> None: """Update Home devices (alarm, light, sensor, switch, remote ...).""" From e208e7da91342f2c3cb9bdbf07b90e2066991766 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 21 Aug 2023 20:03:19 +0200 Subject: [PATCH 115/120] Remove repair issue for MQTT discovered items (#98768) --- homeassistant/components/mqtt/mixins.py | 14 ++++---------- homeassistant/components/mqtt/strings.json | 10 +--------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 70156703155..48b18a61782 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -1144,11 +1144,8 @@ class MqttEntity( ) elif (device_name := config[CONF_DEVICE][CONF_NAME]) == entity_name: self._attr_name = None - self._issue_key = ( - "entity_name_is_device_name_discovery" - if self._discovery - else "entity_name_is_device_name_yaml" - ) + if not self._discovery: + self._issue_key = "entity_name_is_device_name_yaml" _LOGGER.warning( "MQTT device name is equal to entity name in your config %s, " "this is not expected. Please correct your configuration. " @@ -1162,11 +1159,8 @@ class MqttEntity( if device_name[:1].isupper(): # Ensure a capital if the device name first char is a capital new_entity_name = new_entity_name[:1].upper() + new_entity_name[1:] - self._issue_key = ( - "entity_name_startswith_device_name_discovery" - if self._discovery - else "entity_name_startswith_device_name_yaml" - ) + if not self._discovery: + self._issue_key = "entity_name_startswith_device_name_yaml" _LOGGER.warning( "MQTT entity name starts with the device name in your config %s, " "this is not expected. Please correct your configuration. " diff --git a/homeassistant/components/mqtt/strings.json b/homeassistant/components/mqtt/strings.json index 55677798a08..ae6033de5f9 100644 --- a/homeassistant/components/mqtt/strings.json +++ b/homeassistant/components/mqtt/strings.json @@ -14,15 +14,7 @@ }, "entity_name_startswith_device_name_yaml": { "title": "Manual configured MQTT entities with a name that starts with the device name", - "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped of the entity name as a work-a-round. Please update your configuration and restart Home Assistant to fix this issue. \n\nList of affected entities:\n\n{config}" - }, - "entity_name_is_device_name_discovery": { - "title": "Discovered MQTT entities with a name that is equal to the device name", - "description": "Some MQTT entities have an entity name equal to the device name. This is not expected. The entity name is set to `null` as a work-a-round to avoid a duplicate name. Please inform the maintainer of the software application that supplies the affected entities to fix this issue.\n\nList of affected entities:\n\n{config}" - }, - "entity_name_startswith_device_name_discovery": { - "title": "Discovered entities with a name that starts with the device name", - "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped of the entity name as a work-a-round. Please inform the maintainer of the software application that supplies the affected entities to fix this issue. \n\nList of affected entities:\n\n{config}" + "description": "Some MQTT entities have an entity name that starts with the device name. This is not expected. To avoid a duplicate name the device name prefix is stripped off the entity name as a work-a-round. Please update your configuration and restart Home Assistant to fix this issue. \n\nList of affected entities:\n\n{config}" } }, "config": { From 119bc7d84704181c51f92ca6b901ce6a03f2f34b Mon Sep 17 00:00:00 2001 From: tronikos Date: Tue, 22 Aug 2023 03:28:19 -0700 Subject: [PATCH 116/120] Bump androidtvremote2 to 0.0.14 (#98801) --- homeassistant/components/androidtv_remote/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/androidtv_remote/manifest.json b/homeassistant/components/androidtv_remote/manifest.json index cb7a969379e..f45dee34afe 100644 --- a/homeassistant/components/androidtv_remote/manifest.json +++ b/homeassistant/components/androidtv_remote/manifest.json @@ -8,6 +8,6 @@ "iot_class": "local_push", "loggers": ["androidtvremote2"], "quality_scale": "platinum", - "requirements": ["androidtvremote2==0.0.13"], + "requirements": ["androidtvremote2==0.0.14"], "zeroconf": ["_androidtvremote2._tcp.local."] } diff --git a/requirements_all.txt b/requirements_all.txt index 5c267d9ee47..043dae0e38f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -399,7 +399,7 @@ amcrest==1.9.7 androidtv[async]==0.0.70 # homeassistant.components.androidtv_remote -androidtvremote2==0.0.13 +androidtvremote2==0.0.14 # homeassistant.components.anel_pwrctrl anel-pwrctrl-homeassistant==0.0.1.dev2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 72843065df4..0abf3b21c1b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -368,7 +368,7 @@ amberelectric==1.0.4 androidtv[async]==0.0.70 # homeassistant.components.androidtv_remote -androidtvremote2==0.0.13 +androidtvremote2==0.0.14 # homeassistant.components.anova anova-wifi==0.10.0 From 63a687c37f29119707bfbf6eadf49d2d8d993146 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Tue, 15 Aug 2023 03:04:45 -0600 Subject: [PATCH 117/120] Bump pylitterbot to 2023.4.4 (#98414) --- homeassistant/components/litterrobot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/litterrobot/manifest.json b/homeassistant/components/litterrobot/manifest.json index 2a4a3447eb6..81375dd3a6c 100644 --- a/homeassistant/components/litterrobot/manifest.json +++ b/homeassistant/components/litterrobot/manifest.json @@ -12,5 +12,5 @@ "integration_type": "hub", "iot_class": "cloud_push", "loggers": ["pylitterbot"], - "requirements": ["pylitterbot==2023.4.2"] + "requirements": ["pylitterbot==2023.4.4"] } diff --git a/requirements_all.txt b/requirements_all.txt index 043dae0e38f..be4f1b91a2e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1809,7 +1809,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.2 +pylitterbot==2023.4.4 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0abf3b21c1b..c3988754093 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1340,7 +1340,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.2 +pylitterbot==2023.4.4 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 From c8b51919841f5e3b312a69166d16163f31ddbe57 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Wed, 23 Aug 2023 04:19:25 -0600 Subject: [PATCH 118/120] Bump pylitterbot to 2023.4.5 (#98854) --- homeassistant/components/litterrobot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/litterrobot/manifest.json b/homeassistant/components/litterrobot/manifest.json index 81375dd3a6c..9a3334cbaac 100644 --- a/homeassistant/components/litterrobot/manifest.json +++ b/homeassistant/components/litterrobot/manifest.json @@ -12,5 +12,5 @@ "integration_type": "hub", "iot_class": "cloud_push", "loggers": ["pylitterbot"], - "requirements": ["pylitterbot==2023.4.4"] + "requirements": ["pylitterbot==2023.4.5"] } diff --git a/requirements_all.txt b/requirements_all.txt index be4f1b91a2e..e97c191631c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1809,7 +1809,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.4 +pylitterbot==2023.4.5 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c3988754093..b7e9a7d80ee 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1340,7 +1340,7 @@ pylibrespot-java==0.1.1 pylitejet==0.5.0 # homeassistant.components.litterrobot -pylitterbot==2023.4.4 +pylitterbot==2023.4.5 # homeassistant.components.lutron_caseta pylutron-caseta==0.18.1 From e1b005128da1c988bd188cef71a3b8a9ac7e764c Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Thu, 24 Aug 2023 12:01:22 +0200 Subject: [PATCH 119/120] Bump reolink-aio to 0.7.8 (#98942) --- homeassistant/components/reolink/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index f350bb4f948..3ff25d1e7a0 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -18,5 +18,5 @@ "documentation": "https://www.home-assistant.io/integrations/reolink", "iot_class": "local_push", "loggers": ["reolink_aio"], - "requirements": ["reolink-aio==0.7.7"] + "requirements": ["reolink-aio==0.7.8"] } diff --git a/requirements_all.txt b/requirements_all.txt index e97c191631c..34d6b48c0db 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2278,7 +2278,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.7 +reolink-aio==0.7.8 # homeassistant.components.idteck_prox rfk101py==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index b7e9a7d80ee..1000c01a2d2 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1674,7 +1674,7 @@ renault-api==0.1.13 renson-endura-delta==1.5.0 # homeassistant.components.reolink -reolink-aio==0.7.7 +reolink-aio==0.7.8 # homeassistant.components.rflink rflink==0.0.65 From 9bc4866bd28c43aa1e895da0eef558e90d76401d Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Thu, 24 Aug 2023 12:12:41 +0200 Subject: [PATCH 120/120] Bumped version to 2023.8.4 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index db28d072aa5..f803a673265 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from typing import Final APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "3" +PATCH_VERSION: Final = "4" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 11, 0) diff --git a/pyproject.toml b/pyproject.toml index d3e2f065e1c..06b9c965cbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.8.3" +version = "2023.8.4" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"