diff --git a/homeassistant/components/openhome/__init__.py b/homeassistant/components/openhome/__init__.py index 887b7cc71c16..6cfeab19d3b9 100644 --- a/homeassistant/components/openhome/__init__.py +++ b/homeassistant/components/openhome/__init__.py @@ -2,15 +2,15 @@ import logging -import aiohttp -from async_upnp_client.client import UpnpError from openhomedevice.device import Device +from openhomedevice.exceptions import OpenhomeError from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.typing import ConfigType from .const import DOMAIN @@ -37,11 +37,11 @@ async def async_setup_entry( """Set up the configuration config entry.""" _LOGGER.debug("Setting up config entry: %s", config_entry.unique_id) - device = await hass.async_add_executor_job(Device, config_entry.data[CONF_HOST]) + device = Device(config_entry.data[CONF_HOST], session=async_get_clientsession(hass)) try: await device.init() - except (TimeoutError, aiohttp.ClientError, UpnpError) as exc: + except OpenhomeError as exc: raise ConfigEntryNotReady from exc _LOGGER.debug("Initialised device: %s", device.uuid()) diff --git a/homeassistant/components/openhome/manifest.json b/homeassistant/components/openhome/manifest.json index 2f34e44b24e2..22f45f0777fd 100644 --- a/homeassistant/components/openhome/manifest.json +++ b/homeassistant/components/openhome/manifest.json @@ -7,7 +7,7 @@ "integration_type": "device", "iot_class": "local_polling", "loggers": ["async_upnp_client", "openhomedevice"], - "requirements": ["openhomedevice==2.2.0"], + "requirements": ["openhomedevice==2.5"], "ssdp": [ { "st": "urn:av-openhome-org:service:Product:1" diff --git a/homeassistant/components/openhome/media_player.py b/homeassistant/components/openhome/media_player.py index ea63ffe86455..17e6cb44b3da 100644 --- a/homeassistant/components/openhome/media_player.py +++ b/homeassistant/components/openhome/media_player.py @@ -5,8 +5,7 @@ import functools import logging from typing import Any, Concatenate, override -import aiohttp -from async_upnp_client.client import UpnpError +from openhomedevice.exceptions import OpenhomeError from homeassistant.components import media_source from homeassistant.components.media_player import ( @@ -58,7 +57,7 @@ type _ReturnFuncType[_T, **_P, _R] = Callable[ def catch_request_errors[_OpenhomeDeviceT: OpenhomeDevice, **_P, _R]() -> Callable[ [_FuncType[_OpenhomeDeviceT, _P, _R]], _ReturnFuncType[_OpenhomeDeviceT, _P, _R] ]: - """Catch TimeoutError, aiohttp.ClientError, UpnpError errors.""" + """Catch OpenhomeError errors.""" def call_wrapper( func: _FuncType[_OpenhomeDeviceT, _P, _R], @@ -69,11 +68,11 @@ def catch_request_errors[_OpenhomeDeviceT: OpenhomeDevice, **_P, _R]() -> Callab async def wrapper( self: _OpenhomeDeviceT, *args: _P.args, **kwargs: _P.kwargs ) -> _R | None: - """Catch TimeoutError, aiohttp.ClientError, UpnpError errors.""" + """Catch OpenhomeError errors.""" try: return await func(self, *args, **kwargs) - except TimeoutError, aiohttp.ClientError, UpnpError: - _LOGGER.error("Error during call %s", func.__name__) + except OpenhomeError as err: + _LOGGER.error("Error during call %s: %s", func.__name__, err) return None return wrapper @@ -167,7 +166,9 @@ class OpenhomeDevice(MediaPlayerEntity): self._attr_state = MediaPlayerState.PLAYING self._attr_available = True - except TimeoutError, aiohttp.ClientError, UpnpError: + except OpenhomeError as err: + if self._attr_available: + _LOGGER.warning("Error updating %s: %s", self.entity_id, err) self._attr_available = False # pylint: disable-next=home-assistant-action-swallowed-exception @@ -261,8 +262,8 @@ class OpenhomeDevice(MediaPlayerEntity): await self._device.invoke_pin(pin) else: _LOGGER.error("Pins service not supported") - except UpnpError: - _LOGGER.error("Error invoking pin %s", pin) + except OpenhomeError as err: + _LOGGER.error("Error invoking pin %s: %s", pin, err) # pylint: disable-next=home-assistant-action-swallowed-exception @catch_request_errors() diff --git a/homeassistant/components/openhome/update.py b/homeassistant/components/openhome/update.py index e7d9e44c8b1f..4e05cc4f3c11 100644 --- a/homeassistant/components/openhome/update.py +++ b/homeassistant/components/openhome/update.py @@ -3,8 +3,7 @@ import logging from typing import Any, override -import aiohttp -from async_upnp_client.client import UpnpError +from openhomedevice.exceptions import OpenhomeError from homeassistant.components.update import ( UpdateDeviceClass, @@ -92,7 +91,7 @@ class OpenhomeUpdateEntity(UpdateEntity): try: if self.latest_version: await self._device.update_firmware() - except (TimeoutError, aiohttp.ClientError, UpnpError) as err: + except OpenhomeError as err: raise HomeAssistantError( f"Error updating {self._device.device.friendly_name}: {err}" ) from err diff --git a/requirements_all.txt b/requirements_all.txt index f8af75d2f159..9d1faa0b0bfd 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1815,7 +1815,7 @@ openai==2.45.0 openerz-api==0.3.0 # homeassistant.components.openhome -openhomedevice==2.2.0 +openhomedevice==2.5 # homeassistant.components.openrgb openrgb-python==0.3.6 diff --git a/tests/components/openhome/test_init.py b/tests/components/openhome/test_init.py new file mode 100644 index 000000000000..428c9e89c744 --- /dev/null +++ b/tests/components/openhome/test_init.py @@ -0,0 +1,32 @@ +"""Tests for the Openhome integration setup.""" + +from unittest.mock import AsyncMock, MagicMock, patch + +from homeassistant.components.openhome.const import DOMAIN +from homeassistant.config_entries import ConfigEntryState +from homeassistant.const import CONF_HOST +from homeassistant.core import HomeAssistant +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +from tests.common import MockConfigEntry + +HOST = "http://localhost" + + +async def test_device_uses_shared_session(hass: HomeAssistant) -> None: + """Test the device is given Home Assistant's shared aiohttp session.""" + entry = MockConfigEntry(domain=DOMAIN, data={CONF_HOST: HOST}, unique_id="uuid") + entry.add_to_hass(hass) + + with ( + patch("homeassistant.components.openhome.PLATFORMS", []), + patch("homeassistant.components.openhome.Device", MagicMock()) as mock_device, + ): + mock_device.return_value.init = AsyncMock() + mock_device.return_value.uuid = MagicMock(return_value="uuid") + + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.state is ConfigEntryState.LOADED + mock_device.assert_called_once_with(HOST, session=async_get_clientsession(hass))