mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 07:25:52 -05:00
media_player platform fixes for Alexa Devices (#172611)
This commit is contained in:
@@ -204,7 +204,26 @@ class AmazonDevicesCoordinator(DataUpdateCoordinator[dict[str, AmazonDevice]]):
|
||||
|
||||
async def sync_media_state(self) -> None:
|
||||
"""Sync media state."""
|
||||
await self.api.sync_media_state()
|
||||
try:
|
||||
await self.api.sync_media_state()
|
||||
except CannotAuthenticate as err:
|
||||
raise ConfigEntryAuthFailed(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="invalid_auth",
|
||||
translation_placeholders={"error": repr(err)},
|
||||
) from err
|
||||
except (CannotConnect, TimeoutError) as err:
|
||||
raise ConfigEntryNotReady(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="cannot_connect_with_error",
|
||||
translation_placeholders={"error": repr(err)},
|
||||
) from err
|
||||
except (CannotRetrieveData, ValueError) as err:
|
||||
raise ConfigEntryNotReady(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="cannot_retrieve_data_with_error",
|
||||
translation_placeholders={"error": repr(err)},
|
||||
) from err
|
||||
|
||||
async def media_state_event_handler(
|
||||
self, media_state: dict[str, AmazonMediaState]
|
||||
|
||||
@@ -156,9 +156,11 @@ class AlexaDevicesMediaPlayer(AmazonEntity, MediaPlayerEntity):
|
||||
@property
|
||||
def is_volume_muted(self) -> bool | None:
|
||||
"""Return True if the volume is muted."""
|
||||
if not self.volume_state:
|
||||
if not self.volume_state or self.volume_state.volume is None:
|
||||
return None
|
||||
return self.volume_state.volume == 0
|
||||
# is_muted is True when Alexa has muted the device
|
||||
# volume == 0 is where we have muted by setting volume to 0
|
||||
return self.volume_state.is_muted or self.volume_state.volume == 0
|
||||
|
||||
@property
|
||||
def media_title(self) -> str | None:
|
||||
@@ -259,12 +261,20 @@ class AlexaDevicesMediaPlayer(AmazonEntity, MediaPlayerEntity):
|
||||
return
|
||||
if mute:
|
||||
self._prev_volume = self.volume_state.volume
|
||||
target_volume = 0
|
||||
else:
|
||||
if self._prev_volume is None:
|
||||
return
|
||||
target_volume = self._prev_volume
|
||||
await self.async_set_volume_level(0)
|
||||
return
|
||||
|
||||
if self.volume_state.is_muted and self._prev_volume is None:
|
||||
# is muted by Alexa which we can see but not control
|
||||
# when muted this way, volume is still set
|
||||
# changing volume will unmute
|
||||
# if HA set volume to 0 then Alexa muted we just default to 30%
|
||||
self._prev_volume = self.volume_state.volume or 30
|
||||
if self._prev_volume is None:
|
||||
return
|
||||
target_volume = self._prev_volume
|
||||
await self.async_set_volume_level(target_volume / 100)
|
||||
self._prev_volume = None
|
||||
|
||||
@alexa_api_call
|
||||
async def _send_media_command(self, command: AmazonMediaControls) -> None:
|
||||
|
||||
@@ -125,6 +125,9 @@
|
||||
},
|
||||
"invalid_sound_value": {
|
||||
"message": "Invalid sound {sound} specified"
|
||||
},
|
||||
"unknown_exception": {
|
||||
"message": "Unknown error occurred: {error}"
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
|
||||
@@ -126,3 +126,48 @@ async def test_sync_history_state_error(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("side_effect", "expected_state"),
|
||||
[
|
||||
pytest.param(
|
||||
CannotAuthenticate,
|
||||
ConfigEntryState.SETUP_ERROR,
|
||||
id="cannot_authenticate",
|
||||
),
|
||||
pytest.param(
|
||||
CannotConnect,
|
||||
ConfigEntryState.SETUP_RETRY,
|
||||
id="cannot_connect",
|
||||
),
|
||||
pytest.param(
|
||||
TimeoutError,
|
||||
ConfigEntryState.SETUP_RETRY,
|
||||
id="timeout_error",
|
||||
),
|
||||
pytest.param(
|
||||
CannotRetrieveData,
|
||||
ConfigEntryState.SETUP_RETRY,
|
||||
id="cannot_retrieve_data",
|
||||
),
|
||||
pytest.param(
|
||||
ValueError,
|
||||
ConfigEntryState.SETUP_RETRY,
|
||||
id="value_error",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_sync_media_state_auth_failed(
|
||||
hass: HomeAssistant,
|
||||
mock_amazon_devices_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
side_effect: type[Exception],
|
||||
expected_state: ConfigEntryState,
|
||||
) -> None:
|
||||
"""Test setup fails with ConfigEntryAuthFailed when sync_media_state raises CannotAuthenticate."""
|
||||
mock_amazon_devices_client.sync_media_state.side_effect = side_effect
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is expected_state
|
||||
|
||||
@@ -700,3 +700,28 @@ async def test_unmute_volume_without_prev_volume_returns_early(
|
||||
)
|
||||
|
||||
mock_amazon_devices_client.set_device_volume.assert_not_awaited()
|
||||
|
||||
|
||||
async def test_unmute_volume_when_alexa_muted_restores_current_volume(
|
||||
hass: HomeAssistant,
|
||||
mock_amazon_devices_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Unmute restores current volume when device was muted directly by Alexa."""
|
||||
await _setup_media_player_platform(hass, mock_config_entry)
|
||||
|
||||
await _push_volume_state(
|
||||
mock_amazon_devices_client,
|
||||
volume_state=AmazonVolumeState(volume=30, is_muted=True),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_VOLUME_MUTE,
|
||||
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_MEDIA_VOLUME_MUTED: False},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_amazon_devices_client.set_device_volume.assert_awaited_once()
|
||||
assert mock_amazon_devices_client.set_device_volume.call_args.args[1] == 30
|
||||
|
||||
Reference in New Issue
Block a user