Add support for when device is not logged in to HEOS (#22913)
This commit is contained in:
parent
0d2646ba25
commit
4110bd0acf
5 changed files with 82 additions and 17 deletions
|
@ -75,12 +75,16 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||
await controller.disconnect()
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, disconnect_controller)
|
||||
|
||||
# Get players and sources
|
||||
try:
|
||||
players, favorites, inputs = await asyncio.gather(
|
||||
controller.get_players(),
|
||||
controller.get_favorites(),
|
||||
controller.get_input_sources()
|
||||
)
|
||||
players = await controller.get_players()
|
||||
favorites = {}
|
||||
if controller.is_signed_in:
|
||||
favorites = await controller.get_favorites()
|
||||
else:
|
||||
_LOGGER.warning("%s is not logged in to your HEOS account and will"
|
||||
" be unable to retrieve your favorites", host)
|
||||
inputs = await controller.get_input_sources()
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) as error:
|
||||
await controller.disconnect()
|
||||
_LOGGER.debug("Unable to retrieve players and sources: %s", error,
|
||||
|
@ -175,9 +179,11 @@ class SourceManager:
|
|||
retry_attempts = 0
|
||||
while True:
|
||||
try:
|
||||
return await asyncio.gather(
|
||||
controller.get_favorites(),
|
||||
controller.get_input_sources())
|
||||
favorites = {}
|
||||
if controller.is_signed_in:
|
||||
favorites = await controller.get_favorites()
|
||||
inputs = await controller.get_input_sources()
|
||||
return favorites, inputs
|
||||
except (asyncio.TimeoutError, ConnectionError, CommandError) \
|
||||
as error:
|
||||
if retry_attempts < self.max_retry_attempts:
|
||||
|
@ -192,7 +198,8 @@ class SourceManager:
|
|||
return
|
||||
|
||||
async def update_sources(event):
|
||||
if event in const.EVENT_SOURCES_CHANGED:
|
||||
if event in (const.EVENT_SOURCES_CHANGED,
|
||||
const.EVENT_USER_CHANGED):
|
||||
sources = await get_sources()
|
||||
# If throttled, it will return None
|
||||
if sources:
|
||||
|
|
|
@ -141,7 +141,7 @@ class HeosMediaPlayer(MediaPlayerDevice):
|
|||
|
||||
async def async_set_volume_level(self, volume):
|
||||
"""Set volume level, range 0..1."""
|
||||
await self._player.set_volume(volume * 100)
|
||||
await self._player.set_volume(int(volume * 100))
|
||||
|
||||
async def async_update(self):
|
||||
"""Update supported features of the player."""
|
||||
|
|
|
@ -28,6 +28,8 @@ def controller_fixture(players, favorites, input_sources, dispatcher):
|
|||
mock_heos.players = players
|
||||
mock_heos.get_favorites.return_value = favorites
|
||||
mock_heos.get_input_sources.return_value = input_sources
|
||||
mock_heos.is_signed_in = True
|
||||
mock_heos.signed_in_username = "user@user.com"
|
||||
yield mock_heos
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,7 @@ from asynctest import patch
|
|||
from pyheos import CommandError, const
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.heos import (
|
||||
SourceManager, async_setup_entry, async_unload_entry)
|
||||
from homeassistant.components.heos import async_setup_entry, async_unload_entry
|
||||
from homeassistant.components.heos.const import (
|
||||
DATA_CONTROLLER, DATA_SOURCE_MANAGER, DOMAIN)
|
||||
from homeassistant.components.media_player.const import (
|
||||
|
@ -61,7 +60,7 @@ async def test_async_setup_no_config_returns_true(hass, config_entry):
|
|||
|
||||
|
||||
async def test_async_setup_entry_loads_platforms(
|
||||
hass, config_entry, controller):
|
||||
hass, config_entry, controller, input_sources, favorites):
|
||||
"""Test load connects to heos, retrieves players, and loads platforms."""
|
||||
config_entry.add_to_hass(hass)
|
||||
with patch.object(
|
||||
|
@ -71,10 +70,39 @@ async def test_async_setup_entry_loads_platforms(
|
|||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == 1
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.get_players.call_count == 1
|
||||
assert controller.get_favorites.call_count == 1
|
||||
assert controller.get_input_sources.call_count == 1
|
||||
controller.disconnect.assert_not_called()
|
||||
assert hass.data[DOMAIN][DATA_CONTROLLER] == controller
|
||||
assert hass.data[DOMAIN][MEDIA_PLAYER_DOMAIN] == controller.players
|
||||
assert isinstance(hass.data[DOMAIN][DATA_SOURCE_MANAGER], SourceManager)
|
||||
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].favorites == favorites
|
||||
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].inputs == input_sources
|
||||
|
||||
|
||||
async def test_async_setup_entry_not_signed_in_loads_platforms(
|
||||
hass, config_entry, controller, input_sources, caplog):
|
||||
"""Test setup does not retrieve favorites when not logged in."""
|
||||
config_entry.add_to_hass(hass)
|
||||
controller.is_signed_in = False
|
||||
controller.signed_in_username = None
|
||||
with patch.object(
|
||||
hass.config_entries, 'async_forward_entry_setup') as forward_mock:
|
||||
assert await async_setup_entry(hass, config_entry)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert forward_mock.call_count == 1
|
||||
assert controller.connect.call_count == 1
|
||||
assert controller.get_players.call_count == 1
|
||||
assert controller.get_favorites.call_count == 0
|
||||
assert controller.get_input_sources.call_count == 1
|
||||
controller.disconnect.assert_not_called()
|
||||
assert hass.data[DOMAIN][DATA_CONTROLLER] == controller
|
||||
assert hass.data[DOMAIN][MEDIA_PLAYER_DOMAIN] == controller.players
|
||||
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].favorites == {}
|
||||
assert hass.data[DOMAIN][DATA_SOURCE_MANAGER].inputs == input_sources
|
||||
assert "127.0.0.1 is not logged in to your HEOS account and will be " \
|
||||
"unable to retrieve your favorites" in caplog.text
|
||||
|
||||
|
||||
async def test_async_setup_entry_connect_failure(
|
||||
|
@ -138,4 +166,3 @@ async def test_update_sources_retry(hass, config_entry, config, controller,
|
|||
while "Unable to update sources" not in caplog.text:
|
||||
await asyncio.sleep(0.1)
|
||||
assert controller.get_favorites.call_count == 2
|
||||
assert controller.get_input_sources.call_count == 2
|
||||
|
|
|
@ -116,7 +116,12 @@ async def test_updates_start_from_signals(
|
|||
state = hass.states.get('media_player.test_player')
|
||||
assert state.state == STATE_PLAYING
|
||||
|
||||
# Test sources event update
|
||||
|
||||
async def test_updates_from_sources_updated(
|
||||
hass, config_entry, config, controller, input_sources):
|
||||
"""Tests player updates from changes in sources list."""
|
||||
await setup_platform(hass, config_entry, config)
|
||||
player = controller.players[1]
|
||||
event = asyncio.Event()
|
||||
|
||||
async def set_signal():
|
||||
|
@ -124,11 +129,34 @@ async def test_updates_start_from_signals(
|
|||
hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_HEOS_SOURCES_UPDATED, set_signal)
|
||||
|
||||
favorites.clear()
|
||||
input_sources.clear()
|
||||
player.heos.dispatcher.send(
|
||||
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_SOURCES_CHANGED)
|
||||
await event.wait()
|
||||
source_list = hass.data[DOMAIN][DATA_SOURCE_MANAGER].source_list
|
||||
assert len(source_list) == 2
|
||||
state = hass.states.get('media_player.test_player')
|
||||
assert state.attributes[ATTR_INPUT_SOURCE_LIST] == source_list
|
||||
|
||||
|
||||
async def test_updates_from_user_changed(
|
||||
hass, config_entry, config, controller):
|
||||
"""Tests player updates from changes in user."""
|
||||
await setup_platform(hass, config_entry, config)
|
||||
player = controller.players[1]
|
||||
event = asyncio.Event()
|
||||
|
||||
async def set_signal():
|
||||
event.set()
|
||||
hass.helpers.dispatcher.async_dispatcher_connect(
|
||||
SIGNAL_HEOS_SOURCES_UPDATED, set_signal)
|
||||
|
||||
controller.is_signed_in = False
|
||||
controller.signed_in_username = None
|
||||
player.heos.dispatcher.send(
|
||||
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_USER_CHANGED)
|
||||
await event.wait()
|
||||
source_list = hass.data[DOMAIN][DATA_SOURCE_MANAGER].source_list
|
||||
assert len(source_list) == 1
|
||||
state = hass.states.get('media_player.test_player')
|
||||
assert state.attributes[ATTR_INPUT_SOURCE_LIST] == source_list
|
||||
|
@ -194,6 +222,7 @@ async def test_services(hass, config_entry, config, controller):
|
|||
{ATTR_ENTITY_ID: 'media_player.test_player',
|
||||
ATTR_MEDIA_VOLUME_LEVEL: 1}, blocking=True)
|
||||
player.set_volume.assert_called_once_with(100)
|
||||
assert isinstance(player.set_volume.call_args[0][0], int)
|
||||
|
||||
|
||||
async def test_select_favorite(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue