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 01/44] 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 02/44] 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 03/44] 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 04/44] 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 05/44] 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 06/44] 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 07/44] 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 08/44] 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 09/44] 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 10/44] 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 11/44] 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 12/44] 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 13/44] 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 14/44] 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 15/44] 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 16/44] 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 17/44] 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 18/44] 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 19/44] 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 20/44] 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 21/44] 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 22/44] 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 23/44] 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 24/44] 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 25/44] 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 26/44] 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 27/44] 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 28/44] 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 29/44] 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 30/44] 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 31/44] 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 32/44] 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 33/44] 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 34/44] 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 35/44] 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 36/44] 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 37/44] 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 38/44] 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 39/44] 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 40/44] 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 41/44] 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 42/44] 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 43/44] 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 44/44] 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