Fix songpal crash for soundbars without sound modes (#119999)

Getting soundField on soundbar that doesn't support it crash raise an exception, so it make the whole components unavailable. As there is no simple way to know if soundField is supported, I just get all sound settings, and then pick soundField one if present. If not present, then return None to make it continue, it will just have to effect to display no sound mode and not able to select one (Exactly what we want).
This commit is contained in:
BestPig 2024-06-20 13:06:30 +02:00 committed by GitHub
parent 99cae16b75
commit 7c5fcec062
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 54 additions and 3 deletions

View file

@ -140,7 +140,12 @@ class SongpalEntity(MediaPlayerEntity):
async def _get_sound_modes_info(self):
"""Get available sound modes and the active one."""
settings = await self._dev.get_sound_settings("soundField")
for settings in await self._dev.get_sound_settings():
if settings.target == "soundField":
break
else:
return None, {}
if isinstance(settings, Setting):
settings = [settings]

View file

@ -23,7 +23,9 @@ CONF_DATA = {
}
def _create_mocked_device(throw_exception=False, wired_mac=MAC, wireless_mac=None):
def _create_mocked_device(
throw_exception=False, wired_mac=MAC, wireless_mac=None, no_soundfield=False
):
mocked_device = MagicMock()
type(mocked_device).get_supported_methods = AsyncMock(
@ -101,7 +103,14 @@ def _create_mocked_device(throw_exception=False, wired_mac=MAC, wireless_mac=Non
soundField = MagicMock()
soundField.currentValue = "sound_mode2"
soundField.candidate = [sound_mode1, sound_mode2, sound_mode3]
type(mocked_device).get_sound_settings = AsyncMock(return_value=[soundField])
settings = MagicMock()
settings.target = "soundField"
settings.__iter__.return_value = [soundField]
type(mocked_device).get_sound_settings = AsyncMock(
return_value=[] if no_soundfield else [settings]
)
type(mocked_device).set_power = AsyncMock()
type(mocked_device).set_sound_settings = AsyncMock()

View file

@ -159,6 +159,43 @@ async def test_state(
assert entity.unique_id == MAC
async def test_state_nosoundmode(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test state of the entity with no soundField in sound settings."""
mocked_device = _create_mocked_device(no_soundfield=True)
entry = MockConfigEntry(domain=songpal.DOMAIN, data=CONF_DATA)
entry.add_to_hass(hass)
with _patch_media_player_device(mocked_device):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state.name == FRIENDLY_NAME
assert state.state == STATE_ON
attributes = state.as_dict()["attributes"]
assert attributes["volume_level"] == 0.5
assert attributes["is_volume_muted"] is False
assert attributes["source_list"] == ["title1", "title2"]
assert attributes["source"] == "title2"
assert "sound_mode_list" not in attributes
assert "sound_mode" not in attributes
assert attributes["supported_features"] == SUPPORT_SONGPAL
device = device_registry.async_get_device(identifiers={(songpal.DOMAIN, MAC)})
assert device.connections == {(dr.CONNECTION_NETWORK_MAC, MAC)}
assert device.manufacturer == "Sony Corporation"
assert device.name == FRIENDLY_NAME
assert device.sw_version == SW_VERSION
assert device.model == MODEL
entity = entity_registry.async_get(ENTITY_ID)
assert entity.unique_id == MAC
async def test_state_wireless(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,