Improve Sonos error message on UPNP 800 - music service unavailable (#176167)

This commit is contained in:
Pete Sage
2026-07-15 15:32:30 +02:00
committed by GitHub
parent 0f63e05d5a
commit d554d4ce7a
3 changed files with 94 additions and 3 deletions
+21 -3
View File
@@ -16,7 +16,7 @@ from homeassistant.core import CALLBACK_TYPE
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.dispatcher import dispatcher_send
from .const import SONOS_SPEAKER_ACTIVITY
from .const import DOMAIN, SONOS_SPEAKER_ACTIVITY
from .exception import SonosUpdateError
if TYPE_CHECKING:
@@ -30,6 +30,8 @@ if TYPE_CHECKING:
UID_PREFIX = "RINCON_"
UID_POSTFIX = "01400"
UPNP_ERROR_COMMAND_FAILED = "800"
_LOGGER = logging.getLogger(__name__)
type _SonosEntitiesType = (
@@ -76,8 +78,24 @@ def soco_error[_T: _SonosEntitiesType, **_P, _R](
if (target := _find_target_identifier(self, args_soco)) is None:
raise RuntimeError("Unexpected use of soco_error") from err
message = f"Error calling {function} on {target}: {err}"
raise SonosUpdateError(message) from err
translation_key = "call_failed"
placeholders = {
"target": target,
"error": str(err),
}
if error_code is not None:
translation_key = "upnp_call_failed"
placeholders["error_code"] = str(error_code)
if str(error_code) == UPNP_ERROR_COMMAND_FAILED:
translation_key = "upnp_call_failed_music_service_unavailable"
raise SonosUpdateError(
translation_domain=DOMAIN,
translation_key=translation_key,
translation_placeholders=placeholders,
) from err
dispatch_soco = args_soco or self.soco # type: ignore[union-attr]
dispatcher_send(
@@ -109,6 +109,9 @@
"announce_media_error": {
"message": "Announcing clip {media_id} failed {response}"
},
"call_failed": {
"message": "Error on {target}: {error}"
},
"entity_not_found": {
"message": "Entity {entity_id} not found."
},
@@ -141,6 +144,12 @@
},
"toggle_failed": {
"message": "Could not toggle {entity_id}."
},
"upnp_call_failed": {
"message": "Error on {target} (UPnP error code {error_code}): {error}"
},
"upnp_call_failed_music_service_unavailable": {
"message": "Error on {target} (UPnP error code {error_code}): {error}. This may indicate the selected music service is not available on the speaker."
}
},
"issues": {
@@ -13,6 +13,7 @@ from soco.data_structures import (
DidlPlaylistContainer,
SearchResult,
)
from soco.exceptions import SoCoUPnPException
from sonos_websocket.exception import SonosWebsocketError
from syrupy.assertion import SnapshotAssertion
@@ -326,6 +327,69 @@ async def test_play_media_library_content_error(
)
@pytest.mark.parametrize(
("error", "translation_key", "translation_placeholders"),
[
pytest.param(
OSError("Network down"),
"call_failed",
{
"target": "media_player.zone_a",
"error": "Network down",
},
id="generic-error",
),
pytest.param(
SoCoUPnPException("UPnP Error 701 received", "701", ""),
"upnp_call_failed",
{
"target": "media_player.zone_a",
"error": "UPnP Error 701 received",
"error_code": "701",
},
id="upnp-error",
),
pytest.param(
SoCoUPnPException("UPnP Error 800 received", "800", ""),
"upnp_call_failed_music_service_unavailable",
{
"target": "media_player.zone_a",
"error": "UPnP Error 800 received",
"error_code": "800",
},
id="upnp-error-800-music-service-unavailable",
),
],
)
async def test_play_media_error_translation(
hass: HomeAssistant,
soco_factory: SoCoMockFactory,
async_autosetup_sonos,
error: Exception,
translation_key: str,
translation_placeholders: dict[str, str],
) -> None:
"""Test play_media surfaces translated error details for failures."""
soco_mock = soco_factory.mock_list.get("192.168.42.2")
soco_mock.play_uri.side_effect = error
with pytest.raises(HomeAssistantError) as err:
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: "media_player.zone_a",
ATTR_MEDIA_CONTENT_TYPE: "track",
ATTR_MEDIA_CONTENT_ID: _track_url,
ATTR_MEDIA_ENQUEUE: MediaPlayerEnqueue.REPLACE,
},
blocking=True,
)
assert err.value.translation_key == translation_key
assert err.value.translation_placeholders == translation_placeholders
_track_url = "S://192.168.42.100/music/iTunes/The%20Beatles/A%20Hard%20Day%2fs%I%20Should%20Have%20Known%20Better.mp3"