media_player platform fixes for Alexa Devices (#172611)

This commit is contained in:
jameson_uk
2026-06-01 21:01:25 +00:00
committed by Franck Nijhof
parent 7b06228a5a
commit 84f4f876b1
5 changed files with 110 additions and 8 deletions
@@ -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