Bump aiorussound to 4.0.5 (#126774)
* Bump aiorussound to 4.0.4 * Remove unnecessary exception * Bump aiorussound to 4.0.5 * Fixes * Update homeassistant/components/russound_rio/media_player.py --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>pull/126825/head
parent
b766d91f49
commit
7afad1dde9
|
@ -4,10 +4,11 @@ import asyncio
|
|||
import logging
|
||||
|
||||
from aiorussound import RussoundClient, RussoundTcpConnectionHandler
|
||||
from aiorussound.models import CallbackType
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
|
||||
from .const import CONNECT_TIMEOUT, RUSSOUND_RIO_EXCEPTIONS
|
||||
|
@ -24,26 +25,26 @@ async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) ->
|
|||
|
||||
host = entry.data[CONF_HOST]
|
||||
port = entry.data[CONF_PORT]
|
||||
russ = RussoundClient(RussoundTcpConnectionHandler(hass.loop, host, port))
|
||||
client = RussoundClient(RussoundTcpConnectionHandler(host, port))
|
||||
|
||||
@callback
|
||||
def is_connected_updated(connected: bool) -> None:
|
||||
if connected:
|
||||
_LOGGER.warning("Reconnected to controller at %s:%s", host, port)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Disconnected from controller at %s:%s",
|
||||
host,
|
||||
port,
|
||||
)
|
||||
async def _connection_update_callback(
|
||||
_client: RussoundClient, _callback_type: CallbackType
|
||||
) -> None:
|
||||
"""Call when the device is notified of changes."""
|
||||
if _callback_type == CallbackType.CONNECTION:
|
||||
if _client.is_connected():
|
||||
_LOGGER.warning("Reconnected to device at %s", entry.data[CONF_HOST])
|
||||
else:
|
||||
_LOGGER.warning("Disconnected from device at %s", entry.data[CONF_HOST])
|
||||
|
||||
await client.register_state_update_callbacks(_connection_update_callback)
|
||||
|
||||
russ.connection_handler.add_connection_callback(is_connected_updated)
|
||||
try:
|
||||
async with asyncio.timeout(CONNECT_TIMEOUT):
|
||||
await russ.connect()
|
||||
await client.connect()
|
||||
except RUSSOUND_RIO_EXCEPTIONS as err:
|
||||
raise ConfigEntryNotReady(f"Error while connecting to {host}:{port}") from err
|
||||
entry.runtime_data = russ
|
||||
entry.runtime_data = client
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
|
@ -53,6 +54,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) ->
|
|||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
|
||||
await entry.runtime_data.close()
|
||||
await entry.runtime_data.disconnect()
|
||||
|
||||
return unload_ok
|
||||
|
|
|
@ -6,19 +6,14 @@ import asyncio
|
|||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aiorussound import Controller, RussoundClient, RussoundTcpConnectionHandler
|
||||
from aiorussound import RussoundClient, RussoundTcpConnectionHandler
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .const import (
|
||||
CONNECT_TIMEOUT,
|
||||
DOMAIN,
|
||||
RUSSOUND_RIO_EXCEPTIONS,
|
||||
NoPrimaryControllerException,
|
||||
)
|
||||
from .const import CONNECT_TIMEOUT, DOMAIN, RUSSOUND_RIO_EXCEPTIONS
|
||||
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -30,16 +25,6 @@ DATA_SCHEMA = vol.Schema(
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def find_primary_controller_metadata(
|
||||
controllers: dict[int, Controller],
|
||||
) -> tuple[str, str]:
|
||||
"""Find the mac address of the primary Russound controller."""
|
||||
if 1 in controllers:
|
||||
c = controllers[1]
|
||||
return c.mac_address, c.controller_type
|
||||
raise NoPrimaryControllerException
|
||||
|
||||
|
||||
class FlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Russound RIO configuration flow."""
|
||||
|
||||
|
@ -54,28 +39,22 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
|
|||
host = user_input[CONF_HOST]
|
||||
port = user_input[CONF_PORT]
|
||||
|
||||
russ = RussoundClient(
|
||||
RussoundTcpConnectionHandler(self.hass.loop, host, port)
|
||||
)
|
||||
client = RussoundClient(RussoundTcpConnectionHandler(host, port))
|
||||
try:
|
||||
async with asyncio.timeout(CONNECT_TIMEOUT):
|
||||
await russ.connect()
|
||||
controllers = await russ.enumerate_controllers()
|
||||
metadata = find_primary_controller_metadata(controllers)
|
||||
await russ.close()
|
||||
await client.connect()
|
||||
controller = client.controllers[1]
|
||||
await client.disconnect()
|
||||
except RUSSOUND_RIO_EXCEPTIONS:
|
||||
_LOGGER.exception("Could not connect to Russound RIO")
|
||||
errors["base"] = "cannot_connect"
|
||||
except NoPrimaryControllerException:
|
||||
_LOGGER.exception(
|
||||
"Russound RIO device doesn't have a primary controller",
|
||||
)
|
||||
errors["base"] = "no_primary_controller"
|
||||
else:
|
||||
await self.async_set_unique_id(metadata[0])
|
||||
await self.async_set_unique_id(controller.mac_address)
|
||||
self._abort_if_unique_id_configured()
|
||||
data = {CONF_HOST: host, CONF_PORT: port}
|
||||
return self.async_create_entry(title=metadata[1], data=data)
|
||||
return self.async_create_entry(
|
||||
title=controller.controller_type, data=data
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user", data_schema=DATA_SCHEMA, errors=errors
|
||||
|
@ -88,25 +67,19 @@ 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 = RussoundClient(RussoundTcpConnectionHandler(self.hass.loop, host, port))
|
||||
client = RussoundClient(RussoundTcpConnectionHandler(host, port))
|
||||
try:
|
||||
async with asyncio.timeout(CONNECT_TIMEOUT):
|
||||
await russ.connect()
|
||||
controllers = await russ.enumerate_controllers()
|
||||
metadata = find_primary_controller_metadata(controllers)
|
||||
await russ.close()
|
||||
await client.connect()
|
||||
controller = client.controllers[1]
|
||||
await client.disconnect()
|
||||
except RUSSOUND_RIO_EXCEPTIONS:
|
||||
_LOGGER.exception("Could not connect to Russound RIO")
|
||||
return self.async_abort(
|
||||
reason="cannot_connect", description_placeholders={}
|
||||
)
|
||||
except NoPrimaryControllerException:
|
||||
_LOGGER.exception("Russound RIO device doesn't have a primary controller")
|
||||
return self.async_abort(
|
||||
reason="no_primary_controller", description_placeholders={}
|
||||
)
|
||||
else:
|
||||
await self.async_set_unique_id(metadata[0])
|
||||
await self.async_set_unique_id(controller.mac_address)
|
||||
self._abort_if_unique_id_configured()
|
||||
data = {CONF_HOST: host, CONF_PORT: port}
|
||||
return self.async_create_entry(title=metadata[1], data=data)
|
||||
return self.async_create_entry(title=controller.controller_type, data=data)
|
||||
|
|
|
@ -17,10 +17,6 @@ RUSSOUND_RIO_EXCEPTIONS = (
|
|||
)
|
||||
|
||||
|
||||
class NoPrimaryControllerException(Exception):
|
||||
"""Thrown when the Russound device is not the primary unit in the RNET stack."""
|
||||
|
||||
|
||||
CONNECT_TIMEOUT = 5
|
||||
|
||||
MP_FEATURES_BY_FLAG = {
|
||||
|
|
|
@ -4,9 +4,9 @@ from collections.abc import Awaitable, Callable, Coroutine
|
|||
from functools import wraps
|
||||
from typing import Any, Concatenate
|
||||
|
||||
from aiorussound import Controller, RussoundTcpConnectionHandler
|
||||
from aiorussound import Controller, RussoundClient, RussoundTcpConnectionHandler
|
||||
from aiorussound.models import CallbackType
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
@ -46,7 +46,7 @@ class RussoundBaseEntity(Entity):
|
|||
self._client = controller.client
|
||||
self._controller = controller
|
||||
self._primary_mac_address = (
|
||||
controller.mac_address or controller.parent_controller.mac_address
|
||||
controller.mac_address or self._client.controllers[1].mac_address
|
||||
)
|
||||
self._device_identifier = (
|
||||
self._controller.mac_address
|
||||
|
@ -64,30 +64,33 @@ class RussoundBaseEntity(Entity):
|
|||
self._attr_device_info["configuration_url"] = (
|
||||
f"http://{self._client.connection_handler.host}"
|
||||
)
|
||||
if controller.parent_controller:
|
||||
if controller.controller_id != 1:
|
||||
assert self._client.controllers[1].mac_address
|
||||
self._attr_device_info["via_device"] = (
|
||||
DOMAIN,
|
||||
controller.parent_controller.mac_address,
|
||||
self._client.controllers[1].mac_address,
|
||||
)
|
||||
else:
|
||||
assert controller.mac_address
|
||||
self._attr_device_info["connections"] = {
|
||||
(CONNECTION_NETWORK_MAC, controller.mac_address)
|
||||
}
|
||||
|
||||
@callback
|
||||
def _is_connected_updated(self, connected: bool) -> None:
|
||||
"""Update the state when the device is ready to receive commands or is unavailable."""
|
||||
self._attr_available = connected
|
||||
async def _state_update_callback(
|
||||
self, _client: RussoundClient, _callback_type: CallbackType
|
||||
) -> None:
|
||||
"""Call when the device is notified of changes."""
|
||||
if _callback_type == CallbackType.CONNECTION:
|
||||
self._attr_available = _client.is_connected()
|
||||
self._controller = _client.controllers[self._controller.controller_id]
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
self._client.connection_handler.add_connection_callback(
|
||||
self._is_connected_updated
|
||||
)
|
||||
"""Register callback handlers."""
|
||||
await self._client.register_state_update_callbacks(self._state_update_callback)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Remove callbacks."""
|
||||
self._client.connection_handler.remove_connection_callback(
|
||||
self._is_connected_updated
|
||||
await self._client.unregister_state_update_callbacks(
|
||||
self._state_update_callback
|
||||
)
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
"iot_class": "local_push",
|
||||
"loggers": ["aiorussound"],
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["aiorussound==3.1.5"]
|
||||
"requirements": ["aiorussound==4.0.5"]
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
|
||||
from aiorussound import RussoundClient, Source, Zone
|
||||
from aiorussound.models import CallbackType
|
||||
from aiorussound import Controller
|
||||
from aiorussound.models import Source
|
||||
from aiorussound.rio import ZoneControlSurface
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
MediaPlayerDeviceClass,
|
||||
|
@ -15,8 +16,7 @@ from homeassistant.components.media_player import (
|
|||
MediaType,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_IMPORT
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
|
@ -83,31 +83,14 @@ async def async_setup_entry(
|
|||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Russound RIO platform."""
|
||||
russ = entry.runtime_data
|
||||
client = entry.runtime_data
|
||||
sources = client.sources
|
||||
|
||||
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():
|
||||
for zone in controller.zones.values():
|
||||
await zone.watch()
|
||||
mp = RussoundZoneDevice(zone, sources)
|
||||
entities.append(mp)
|
||||
|
||||
@callback
|
||||
def on_stop(event):
|
||||
"""Shutdown cleanly when hass stops."""
|
||||
hass.loop.create_task(russ.close())
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_stop)
|
||||
|
||||
async_add_entities(entities)
|
||||
async_add_entities(
|
||||
RussoundZoneDevice(controller, zone_id, sources)
|
||||
for controller in client.controllers.values()
|
||||
for zone_id in controller.zones
|
||||
)
|
||||
|
||||
|
||||
class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
|
||||
|
@ -123,42 +106,32 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
|
|||
| MediaPlayerEntityFeature.SELECT_SOURCE
|
||||
)
|
||||
|
||||
def __init__(self, zone: Zone, sources: dict[int, Source]) -> None:
|
||||
def __init__(
|
||||
self, controller: Controller, zone_id: int, sources: dict[int, Source]
|
||||
) -> None:
|
||||
"""Initialize the zone device."""
|
||||
super().__init__(zone.controller)
|
||||
self._zone = zone
|
||||
super().__init__(controller)
|
||||
self._zone_id = zone_id
|
||||
_zone = self._zone
|
||||
self._sources = sources
|
||||
self._attr_name = zone.name
|
||||
self._attr_unique_id = f"{self._primary_mac_address}-{zone.device_str()}"
|
||||
self._attr_name = _zone.name
|
||||
self._attr_unique_id = f"{self._primary_mac_address}-{_zone.device_str}"
|
||||
for flag, feature in MP_FEATURES_BY_FLAG.items():
|
||||
if flag in zone.client.supported_features:
|
||||
if flag in self._client.supported_features:
|
||||
self._attr_supported_features |= feature
|
||||
|
||||
async def _state_update_callback(
|
||||
self, _client: RussoundClient, _callback_type: CallbackType
|
||||
) -> None:
|
||||
"""Call when the device is notified of changes."""
|
||||
self.async_write_ha_state()
|
||||
@property
|
||||
def _zone(self) -> ZoneControlSurface:
|
||||
return self._controller.zones[self._zone_id]
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callback handlers."""
|
||||
await super().async_added_to_hass()
|
||||
await self._client.register_state_update_callbacks(self._state_update_callback)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Remove callbacks."""
|
||||
await super().async_will_remove_from_hass()
|
||||
await self._client.unregister_state_update_callbacks(
|
||||
self._state_update_callback
|
||||
)
|
||||
|
||||
def _current_source(self) -> Source:
|
||||
@property
|
||||
def _source(self) -> Source:
|
||||
return self._zone.fetch_current_source()
|
||||
|
||||
@property
|
||||
def state(self) -> MediaPlayerState | None:
|
||||
"""Return the state of the device."""
|
||||
status = self._zone.properties.status
|
||||
status = self._zone.status
|
||||
if status == "ON":
|
||||
return MediaPlayerState.ON
|
||||
if status == "OFF":
|
||||
|
@ -168,7 +141,7 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def source(self):
|
||||
"""Get the currently selected source."""
|
||||
return self._current_source().name
|
||||
return self._source.name
|
||||
|
||||
@property
|
||||
def source_list(self):
|
||||
|
@ -178,22 +151,22 @@ class RussoundZoneDevice(RussoundBaseEntity, MediaPlayerEntity):
|
|||
@property
|
||||
def media_title(self):
|
||||
"""Title of current playing media."""
|
||||
return self._current_source().properties.song_name
|
||||
return self._source.song_name
|
||||
|
||||
@property
|
||||
def media_artist(self):
|
||||
"""Artist of current playing media, music track only."""
|
||||
return self._current_source().properties.artist_name
|
||||
return self._source.artist_name
|
||||
|
||||
@property
|
||||
def media_album_name(self):
|
||||
"""Album name of current playing media, music track only."""
|
||||
return self._current_source().properties.album_name
|
||||
return self._source.album_name
|
||||
|
||||
@property
|
||||
def media_image_url(self):
|
||||
"""Image url of current playing media."""
|
||||
return self._current_source().properties.cover_art_url
|
||||
return self._source.cover_art_url
|
||||
|
||||
@property
|
||||
def volume_level(self):
|
||||
|
@ -202,7 +175,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.properties.volume or "0") / 50.0
|
||||
return float(self._zone.volume or "0") / 50.0
|
||||
|
||||
@command
|
||||
async def async_turn_off(self) -> None:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"common": {
|
||||
"error_cannot_connect": "Failed to connect to Russound device. Please make sure the device is powered up and connected to the network. Try power-cycling the device if it does not connect.",
|
||||
"error_no_primary_controller": "No primary controller was detected for the Russound device. Please make sure that the target Russound device has it's controller ID set to 1 (using the selector on the back of the unit)."
|
||||
"error_cannot_connect": "Failed to connect to Russound device. Please make sure the device is powered up and connected to the network. Try power-cycling the device if it does not connect."
|
||||
},
|
||||
"config": {
|
||||
"step": {
|
||||
|
@ -14,12 +13,10 @@
|
|||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:component::russound_rio::common::error_cannot_connect%]",
|
||||
"no_primary_controller": "[%key:component::russound_rio::common::error_no_primary_controller%]"
|
||||
"cannot_connect": "[%key:component::russound_rio::common::error_cannot_connect%]"
|
||||
},
|
||||
"abort": {
|
||||
"cannot_connect": "[%key:component::russound_rio::common::error_cannot_connect%]",
|
||||
"no_primary_controller": "[%key:component::russound_rio::common::error_no_primary_controller%]",
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -356,7 +356,7 @@ aioridwell==2024.01.0
|
|||
aioruckus==0.41
|
||||
|
||||
# homeassistant.components.russound_rio
|
||||
aiorussound==3.1.5
|
||||
aiorussound==4.0.5
|
||||
|
||||
# homeassistant.components.ruuvi_gateway
|
||||
aioruuvigateway==0.1.0
|
||||
|
|
|
@ -338,7 +338,7 @@ aioridwell==2024.01.0
|
|||
aioruckus==0.41
|
||||
|
||||
# homeassistant.components.russound_rio
|
||||
aiorussound==3.1.5
|
||||
aiorussound==4.0.5
|
||||
|
||||
# homeassistant.components.ruuvi_gateway
|
||||
aioruuvigateway==0.1.0
|
||||
|
|
|
@ -44,5 +44,5 @@ def mock_russound() -> Generator[AsyncMock]:
|
|||
return_value=mock_client,
|
||||
),
|
||||
):
|
||||
mock_client.enumerate_controllers.return_value = MOCK_CONTROLLERS
|
||||
mock_client.controllers = MOCK_CONTROLLERS
|
||||
yield mock_client
|
||||
|
|
|
@ -7,7 +7,7 @@ from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
from .const import MOCK_CONFIG, MOCK_CONTROLLERS, MODEL
|
||||
from .const import MOCK_CONFIG, MODEL
|
||||
|
||||
|
||||
async def test_form(
|
||||
|
@ -60,37 +60,6 @@ async def test_form_cannot_connect(
|
|||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_no_primary_controller(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_russound: AsyncMock
|
||||
) -> None:
|
||||
"""Test we handle no primary controller error."""
|
||||
mock_russound.enumerate_controllers.return_value = {}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
user_input = MOCK_CONFIG
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"] == {"base": "no_primary_controller"}
|
||||
|
||||
# Recover with correct information
|
||||
mock_russound.enumerate_controllers.return_value = MOCK_CONTROLLERS
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
MOCK_CONFIG,
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == MODEL
|
||||
assert result["data"] == MOCK_CONFIG
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_import(
|
||||
hass: HomeAssistant, mock_setup_entry: AsyncMock, mock_russound: AsyncMock
|
||||
) -> None:
|
||||
|
@ -119,17 +88,3 @@ async def test_import_cannot_connect(
|
|||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "cannot_connect"
|
||||
|
||||
|
||||
async def test_import_no_primary_controller(
|
||||
hass: HomeAssistant, mock_russound: AsyncMock
|
||||
) -> None:
|
||||
"""Test import with no primary controller error."""
|
||||
mock_russound.enumerate_controllers.return_value = {}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=MOCK_CONFIG
|
||||
)
|
||||
|
||||
assert result["type"] is FlowResultType.ABORT
|
||||
assert result["reason"] == "no_primary_controller"
|
||||
|
|
Loading…
Reference in New Issue