From 8d239d368b57b888b9b815ca1bf61be3ab36b75c Mon Sep 17 00:00:00 2001 From: Noah Husby <32528627+noahhusby@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:22:39 -0400 Subject: [PATCH] Bump aiorussound to 3.0.4 (#125285) feat: bump aiorussound to 3.0.4 --- .../components/russound_rio/__init__.py | 10 ++++----- .../components/russound_rio/config_flow.py | 9 ++++---- .../components/russound_rio/const.py | 4 ++-- .../components/russound_rio/entity.py | 15 +++++++++---- .../components/russound_rio/manifest.json | 2 +- .../components/russound_rio/media_player.py | 22 ++++++++++--------- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/russound_rio/conftest.py | 4 ++-- 9 files changed, 39 insertions(+), 31 deletions(-) diff --git a/homeassistant/components/russound_rio/__init__.py b/homeassistant/components/russound_rio/__init__.py index 8627c636ef2..823d0736037 100644 --- a/homeassistant/components/russound_rio/__init__.py +++ b/homeassistant/components/russound_rio/__init__.py @@ -3,7 +3,7 @@ import asyncio import logging -from aiorussound import Russound +from aiorussound import RussoundClient, RussoundTcpConnectionHandler from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_PORT, Platform @@ -16,7 +16,7 @@ PLATFORMS = [Platform.MEDIA_PLAYER] _LOGGER = logging.getLogger(__name__) -type RussoundConfigEntry = ConfigEntry[Russound] +type RussoundConfigEntry = ConfigEntry[RussoundClient] async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) -> bool: @@ -24,7 +24,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) -> host = entry.data[CONF_HOST] port = entry.data[CONF_PORT] - russ = Russound(hass.loop, host, port) + russ = RussoundClient(RussoundTcpConnectionHandler(hass.loop, host, port)) @callback def is_connected_updated(connected: bool) -> None: @@ -37,14 +37,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) -> port, ) - russ.add_connection_callback(is_connected_updated) - + russ.connection_handler.add_connection_callback(is_connected_updated) try: async with asyncio.timeout(CONNECT_TIMEOUT): await russ.connect() except RUSSOUND_RIO_EXCEPTIONS as err: raise ConfigEntryNotReady(f"Error while connecting to {host}:{port}") from err - entry.runtime_data = russ await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/russound_rio/config_flow.py b/homeassistant/components/russound_rio/config_flow.py index df173d29f61..03e32f39c08 100644 --- a/homeassistant/components/russound_rio/config_flow.py +++ b/homeassistant/components/russound_rio/config_flow.py @@ -6,7 +6,7 @@ import asyncio import logging from typing import Any -from aiorussound import Controller, Russound +from aiorussound import Controller, RussoundClient, RussoundTcpConnectionHandler import voluptuous as vol from homeassistant.config_entries import ConfigFlow, ConfigFlowResult @@ -54,8 +54,9 @@ class FlowHandler(ConfigFlow, domain=DOMAIN): host = user_input[CONF_HOST] port = user_input[CONF_PORT] - controllers = None - russ = Russound(self.hass.loop, host, port) + russ = RussoundClient( + RussoundTcpConnectionHandler(self.hass.loop, host, port) + ) try: async with asyncio.timeout(CONNECT_TIMEOUT): await russ.connect() @@ -87,7 +88,7 @@ class FlowHandler(ConfigFlow, domain=DOMAIN): port = import_data.get(CONF_PORT, 9621) # Connection logic is repeated here since this method will be removed in future releases - russ = Russound(self.hass.loop, host, port) + russ = RussoundClient(RussoundTcpConnectionHandler(self.hass.loop, host, port)) try: async with asyncio.timeout(CONNECT_TIMEOUT): await russ.connect() diff --git a/homeassistant/components/russound_rio/const.py b/homeassistant/components/russound_rio/const.py index d1f4e1c4c0e..42a1db5f2ad 100644 --- a/homeassistant/components/russound_rio/const.py +++ b/homeassistant/components/russound_rio/const.py @@ -2,7 +2,7 @@ import asyncio -from aiorussound import CommandException +from aiorussound import CommandError from aiorussound.const import FeatureFlag from homeassistant.components.media_player import MediaPlayerEntityFeature @@ -10,7 +10,7 @@ from homeassistant.components.media_player import MediaPlayerEntityFeature DOMAIN = "russound_rio" RUSSOUND_RIO_EXCEPTIONS = ( - CommandException, + CommandError, ConnectionRefusedError, TimeoutError, asyncio.CancelledError, diff --git a/homeassistant/components/russound_rio/entity.py b/homeassistant/components/russound_rio/entity.py index 0e4d5cf7dde..4d458118939 100644 --- a/homeassistant/components/russound_rio/entity.py +++ b/homeassistant/components/russound_rio/entity.py @@ -4,7 +4,7 @@ from collections.abc import Awaitable, Callable, Coroutine from functools import wraps from typing import Any, Concatenate -from aiorussound import Controller +from aiorussound import Controller, RussoundTcpConnectionHandler from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError @@ -53,7 +53,6 @@ class RussoundBaseEntity(Entity): or f"{self._primary_mac_address}-{self._controller.controller_id}" ) self._attr_device_info = DeviceInfo( - configuration_url=f"http://{self._instance.host}", # Use MAC address of Russound device as identifier identifiers={(DOMAIN, self._device_identifier)}, manufacturer="Russound", @@ -61,6 +60,10 @@ class RussoundBaseEntity(Entity): model=controller.controller_type, sw_version=controller.firmware_version, ) + if isinstance(self._instance.connection_handler, RussoundTcpConnectionHandler): + self._attr_device_info["configuration_url"] = ( + f"http://{self._instance.connection_handler.host}" + ) if controller.parent_controller: self._attr_device_info["via_device"] = ( DOMAIN, @@ -79,8 +82,12 @@ class RussoundBaseEntity(Entity): async def async_added_to_hass(self) -> None: """Register callbacks.""" - self._instance.add_connection_callback(self._is_connected_updated) + self._instance.connection_handler.add_connection_callback( + self._is_connected_updated + ) async def async_will_remove_from_hass(self) -> None: """Remove callbacks.""" - self._instance.remove_connection_callback(self._is_connected_updated) + self._instance.connection_handler.remove_connection_callback( + self._is_connected_updated + ) diff --git a/homeassistant/components/russound_rio/manifest.json b/homeassistant/components/russound_rio/manifest.json index 6c473d94874..19273de92ee 100644 --- a/homeassistant/components/russound_rio/manifest.json +++ b/homeassistant/components/russound_rio/manifest.json @@ -7,5 +7,5 @@ "iot_class": "local_push", "loggers": ["aiorussound"], "quality_scale": "silver", - "requirements": ["aiorussound==2.3.2"] + "requirements": ["aiorussound==3.0.4"] } diff --git a/homeassistant/components/russound_rio/media_player.py b/homeassistant/components/russound_rio/media_player.py index 20aaf0f3c08..a5bb392a028 100644 --- a/homeassistant/components/russound_rio/media_player.py +++ b/homeassistant/components/russound_rio/media_player.py @@ -84,14 +84,16 @@ async def async_setup_entry( """Set up the Russound RIO platform.""" russ = entry.runtime_data + await russ.init_sources() + sources = russ.sources + for source in sources.values(): + await source.watch() + # Discover controllers controllers = await russ.enumerate_controllers() entities = [] for controller in controllers.values(): - sources = controller.sources - for source in sources.values(): - await source.watch() for zone in controller.zones.values(): await zone.watch() mp = RussoundZoneDevice(zone, sources) @@ -154,7 +156,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity): @property def state(self) -> MediaPlayerState | None: """Return the state of the device.""" - status = self._zone.status + status = self._zone.properties.status if status == "ON": return MediaPlayerState.ON if status == "OFF": @@ -174,22 +176,22 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity): @property def media_title(self): """Title of current playing media.""" - return self._current_source().song_name + return self._current_source().properties.song_name @property def media_artist(self): """Artist of current playing media, music track only.""" - return self._current_source().artist_name + return self._current_source().properties.artist_name @property def media_album_name(self): """Album name of current playing media, music track only.""" - return self._current_source().album_name + return self._current_source().properties.album_name @property def media_image_url(self): """Image url of current playing media.""" - return self._current_source().cover_art_url + return self._current_source().properties.cover_art_url @property def volume_level(self): @@ -198,7 +200,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity): Value is returned based on a range (0..50). Therefore float divide by 50 to get to the required range. """ - return float(self._zone.volume or "0") / 50.0 + return float(self._zone.properties.volume or "0") / 50.0 @command async def async_turn_off(self) -> None: @@ -214,7 +216,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity): async def async_set_volume_level(self, volume: float) -> None: """Set the volume level.""" rvol = int(volume * 50.0) - await self._zone.set_volume(rvol) + await self._zone.set_volume(str(rvol)) @command async def async_select_source(self, source: str) -> None: diff --git a/requirements_all.txt b/requirements_all.txt index c6a8eba7b6f..6a215b2989c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -350,7 +350,7 @@ aioridwell==2024.01.0 aioruckus==0.41 # homeassistant.components.russound_rio -aiorussound==2.3.2 +aiorussound==3.0.4 # homeassistant.components.ruuvi_gateway aioruuvigateway==0.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index da62c029875..74d792acb15 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -332,7 +332,7 @@ aioridwell==2024.01.0 aioruckus==0.41 # homeassistant.components.russound_rio -aiorussound==2.3.2 +aiorussound==3.0.4 # homeassistant.components.ruuvi_gateway aioruuvigateway==0.1.0 diff --git a/tests/components/russound_rio/conftest.py b/tests/components/russound_rio/conftest.py index a87d0a74fa8..344c743d0b3 100644 --- a/tests/components/russound_rio/conftest.py +++ b/tests/components/russound_rio/conftest.py @@ -37,10 +37,10 @@ def mock_russound() -> Generator[AsyncMock]: """Mock the Russound RIO client.""" with ( patch( - "homeassistant.components.russound_rio.Russound", autospec=True + "homeassistant.components.russound_rio.RussoundClient", autospec=True ) as mock_client, patch( - "homeassistant.components.russound_rio.config_flow.Russound", + "homeassistant.components.russound_rio.config_flow.RussoundClient", return_value=mock_client, ), ):