Bump aiorussound to 3.0.4 (#125285)

feat: bump aiorussound to 3.0.4
This commit is contained in:
Noah Husby 2024-09-06 09:22:39 -04:00 committed by GitHub
parent 3a5309e9a0
commit 8d239d368b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 39 additions and 31 deletions

View file

@ -3,7 +3,7 @@
import asyncio import asyncio
import logging import logging
from aiorussound import Russound from aiorussound import RussoundClient, RussoundTcpConnectionHandler
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, Platform from homeassistant.const import CONF_HOST, CONF_PORT, Platform
@ -16,7 +16,7 @@ PLATFORMS = [Platform.MEDIA_PLAYER]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
type RussoundConfigEntry = ConfigEntry[Russound] type RussoundConfigEntry = ConfigEntry[RussoundClient]
async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) -> bool: 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] host = entry.data[CONF_HOST]
port = entry.data[CONF_PORT] port = entry.data[CONF_PORT]
russ = Russound(hass.loop, host, port) russ = RussoundClient(RussoundTcpConnectionHandler(hass.loop, host, port))
@callback @callback
def is_connected_updated(connected: bool) -> None: def is_connected_updated(connected: bool) -> None:
@ -37,14 +37,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) ->
port, port,
) )
russ.add_connection_callback(is_connected_updated) russ.connection_handler.add_connection_callback(is_connected_updated)
try: try:
async with asyncio.timeout(CONNECT_TIMEOUT): async with asyncio.timeout(CONNECT_TIMEOUT):
await russ.connect() await russ.connect()
except RUSSOUND_RIO_EXCEPTIONS as err: except RUSSOUND_RIO_EXCEPTIONS as err:
raise ConfigEntryNotReady(f"Error while connecting to {host}:{port}") from err raise ConfigEntryNotReady(f"Error while connecting to {host}:{port}") from err
entry.runtime_data = russ entry.runtime_data = russ
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

View file

@ -6,7 +6,7 @@ import asyncio
import logging import logging
from typing import Any from typing import Any
from aiorussound import Controller, Russound from aiorussound import Controller, RussoundClient, RussoundTcpConnectionHandler
import voluptuous as vol import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@ -54,8 +54,9 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
host = user_input[CONF_HOST] host = user_input[CONF_HOST]
port = user_input[CONF_PORT] port = user_input[CONF_PORT]
controllers = None russ = RussoundClient(
russ = Russound(self.hass.loop, host, port) RussoundTcpConnectionHandler(self.hass.loop, host, port)
)
try: try:
async with asyncio.timeout(CONNECT_TIMEOUT): async with asyncio.timeout(CONNECT_TIMEOUT):
await russ.connect() await russ.connect()
@ -87,7 +88,7 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
port = import_data.get(CONF_PORT, 9621) port = import_data.get(CONF_PORT, 9621)
# Connection logic is repeated here since this method will be removed in future releases # 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: try:
async with asyncio.timeout(CONNECT_TIMEOUT): async with asyncio.timeout(CONNECT_TIMEOUT):
await russ.connect() await russ.connect()

View file

@ -2,7 +2,7 @@
import asyncio import asyncio
from aiorussound import CommandException from aiorussound import CommandError
from aiorussound.const import FeatureFlag from aiorussound.const import FeatureFlag
from homeassistant.components.media_player import MediaPlayerEntityFeature from homeassistant.components.media_player import MediaPlayerEntityFeature
@ -10,7 +10,7 @@ from homeassistant.components.media_player import MediaPlayerEntityFeature
DOMAIN = "russound_rio" DOMAIN = "russound_rio"
RUSSOUND_RIO_EXCEPTIONS = ( RUSSOUND_RIO_EXCEPTIONS = (
CommandException, CommandError,
ConnectionRefusedError, ConnectionRefusedError,
TimeoutError, TimeoutError,
asyncio.CancelledError, asyncio.CancelledError,

View file

@ -4,7 +4,7 @@ from collections.abc import Awaitable, Callable, Coroutine
from functools import wraps from functools import wraps
from typing import Any, Concatenate from typing import Any, Concatenate
from aiorussound import Controller from aiorussound import Controller, RussoundTcpConnectionHandler
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
@ -53,7 +53,6 @@ class RussoundBaseEntity(Entity):
or f"{self._primary_mac_address}-{self._controller.controller_id}" or f"{self._primary_mac_address}-{self._controller.controller_id}"
) )
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
configuration_url=f"http://{self._instance.host}",
# Use MAC address of Russound device as identifier # Use MAC address of Russound device as identifier
identifiers={(DOMAIN, self._device_identifier)}, identifiers={(DOMAIN, self._device_identifier)},
manufacturer="Russound", manufacturer="Russound",
@ -61,6 +60,10 @@ class RussoundBaseEntity(Entity):
model=controller.controller_type, model=controller.controller_type,
sw_version=controller.firmware_version, 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: if controller.parent_controller:
self._attr_device_info["via_device"] = ( self._attr_device_info["via_device"] = (
DOMAIN, DOMAIN,
@ -79,8 +82,12 @@ class RussoundBaseEntity(Entity):
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
"""Register callbacks.""" """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: async def async_will_remove_from_hass(self) -> None:
"""Remove callbacks.""" """Remove callbacks."""
self._instance.remove_connection_callback(self._is_connected_updated) self._instance.connection_handler.remove_connection_callback(
self._is_connected_updated
)

View file

@ -7,5 +7,5 @@
"iot_class": "local_push", "iot_class": "local_push",
"loggers": ["aiorussound"], "loggers": ["aiorussound"],
"quality_scale": "silver", "quality_scale": "silver",
"requirements": ["aiorussound==2.3.2"] "requirements": ["aiorussound==3.0.4"]
} }

View file

@ -84,14 +84,16 @@ async def async_setup_entry(
"""Set up the Russound RIO platform.""" """Set up the Russound RIO platform."""
russ = entry.runtime_data russ = entry.runtime_data
await russ.init_sources()
sources = russ.sources
for source in sources.values():
await source.watch()
# Discover controllers # Discover controllers
controllers = await russ.enumerate_controllers() controllers = await russ.enumerate_controllers()
entities = [] entities = []
for controller in controllers.values(): for controller in controllers.values():
sources = controller.sources
for source in sources.values():
await source.watch()
for zone in controller.zones.values(): for zone in controller.zones.values():
await zone.watch() await zone.watch()
mp = RussoundZoneDevice(zone, sources) mp = RussoundZoneDevice(zone, sources)
@ -154,7 +156,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
@property @property
def state(self) -> MediaPlayerState | None: def state(self) -> MediaPlayerState | None:
"""Return the state of the device.""" """Return the state of the device."""
status = self._zone.status status = self._zone.properties.status
if status == "ON": if status == "ON":
return MediaPlayerState.ON return MediaPlayerState.ON
if status == "OFF": if status == "OFF":
@ -174,22 +176,22 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
@property @property
def media_title(self): def media_title(self):
"""Title of current playing media.""" """Title of current playing media."""
return self._current_source().song_name return self._current_source().properties.song_name
@property @property
def media_artist(self): def media_artist(self):
"""Artist of current playing media, music track only.""" """Artist of current playing media, music track only."""
return self._current_source().artist_name return self._current_source().properties.artist_name
@property @property
def media_album_name(self): def media_album_name(self):
"""Album name of current playing media, music track only.""" """Album name of current playing media, music track only."""
return self._current_source().album_name return self._current_source().properties.album_name
@property @property
def media_image_url(self): def media_image_url(self):
"""Image url of current playing media.""" """Image url of current playing media."""
return self._current_source().cover_art_url return self._current_source().properties.cover_art_url
@property @property
def volume_level(self): def volume_level(self):
@ -198,7 +200,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
Value is returned based on a range (0..50). Value is returned based on a range (0..50).
Therefore float divide by 50 to get to the required range. 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 @command
async def async_turn_off(self) -> None: 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: async def async_set_volume_level(self, volume: float) -> None:
"""Set the volume level.""" """Set the volume level."""
rvol = int(volume * 50.0) rvol = int(volume * 50.0)
await self._zone.set_volume(rvol) await self._zone.set_volume(str(rvol))
@command @command
async def async_select_source(self, source: str) -> None: async def async_select_source(self, source: str) -> None:

View file

@ -350,7 +350,7 @@ aioridwell==2024.01.0
aioruckus==0.41 aioruckus==0.41
# homeassistant.components.russound_rio # homeassistant.components.russound_rio
aiorussound==2.3.2 aiorussound==3.0.4
# homeassistant.components.ruuvi_gateway # homeassistant.components.ruuvi_gateway
aioruuvigateway==0.1.0 aioruuvigateway==0.1.0

View file

@ -332,7 +332,7 @@ aioridwell==2024.01.0
aioruckus==0.41 aioruckus==0.41
# homeassistant.components.russound_rio # homeassistant.components.russound_rio
aiorussound==2.3.2 aiorussound==3.0.4
# homeassistant.components.ruuvi_gateway # homeassistant.components.ruuvi_gateway
aioruuvigateway==0.1.0 aioruuvigateway==0.1.0

View file

@ -37,10 +37,10 @@ def mock_russound() -> Generator[AsyncMock]:
"""Mock the Russound RIO client.""" """Mock the Russound RIO client."""
with ( with (
patch( patch(
"homeassistant.components.russound_rio.Russound", autospec=True "homeassistant.components.russound_rio.RussoundClient", autospec=True
) as mock_client, ) as mock_client,
patch( patch(
"homeassistant.components.russound_rio.config_flow.Russound", "homeassistant.components.russound_rio.config_flow.RussoundClient",
return_value=mock_client, return_value=mock_client,
), ),
): ):