mirror of
https://github.com/home-assistant/core.git
synced 2025-12-25 05:26:47 +00:00
Fix Sonos Dialog Select type conversion part II (#152491)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
@@ -59,17 +59,12 @@ async def async_setup_entry(
|
||||
for select_data in SELECT_TYPES:
|
||||
if select_data.speaker_model == speaker.model_name.upper():
|
||||
if (
|
||||
state := getattr(speaker.soco, select_data.soco_attribute, None)
|
||||
) is not None:
|
||||
try:
|
||||
setattr(speaker, select_data.speaker_attribute, int(state))
|
||||
features.append(select_data)
|
||||
except ValueError:
|
||||
_LOGGER.error(
|
||||
"Invalid value for %s %s",
|
||||
select_data.speaker_attribute,
|
||||
state,
|
||||
)
|
||||
speaker.update_soco_int_attribute(
|
||||
select_data.soco_attribute, select_data.speaker_attribute
|
||||
)
|
||||
is not None
|
||||
):
|
||||
features.append(select_data)
|
||||
return features
|
||||
|
||||
async def _async_create_entities(speaker: SonosSpeaker) -> None:
|
||||
@@ -112,8 +107,9 @@ class SonosSelectEntity(SonosEntity, SelectEntity):
|
||||
@soco_error()
|
||||
def poll_state(self) -> None:
|
||||
"""Poll the device for the current state."""
|
||||
state = getattr(self.soco, self.soco_attribute)
|
||||
setattr(self.speaker, self.speaker_attribute, state)
|
||||
self.speaker.update_soco_int_attribute(
|
||||
self.soco_attribute, self.speaker_attribute
|
||||
)
|
||||
|
||||
@property
|
||||
def current_option(self) -> str | None:
|
||||
|
||||
@@ -275,6 +275,29 @@ class SonosSpeaker:
|
||||
"""Write states for associated SonosEntity instances."""
|
||||
async_dispatcher_send(self.hass, f"{SONOS_STATE_UPDATED}-{self.soco.uid}")
|
||||
|
||||
def update_soco_int_attribute(
|
||||
self, soco_attribute: str, speaker_attribute: str
|
||||
) -> int | None:
|
||||
"""Update an integer attribute from SoCo and set it on the speaker.
|
||||
|
||||
Returns the integer value if successful, otherwise None. Do not call from
|
||||
async context as it is a blocking function.
|
||||
"""
|
||||
value: int | None = None
|
||||
if (state := getattr(self.soco, soco_attribute, None)) is None:
|
||||
_LOGGER.error("Missing value for %s", speaker_attribute)
|
||||
else:
|
||||
try:
|
||||
value = int(state)
|
||||
except (TypeError, ValueError):
|
||||
_LOGGER.error(
|
||||
"Invalid value for %s %s",
|
||||
speaker_attribute,
|
||||
state,
|
||||
)
|
||||
setattr(self, speaker_attribute, value)
|
||||
return value
|
||||
|
||||
#
|
||||
# Properties
|
||||
#
|
||||
|
||||
@@ -88,6 +88,36 @@ async def test_select_dialog_invalid_level(
|
||||
assert dialog_level_state.state == STATE_UNKNOWN
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("value", "result"),
|
||||
[
|
||||
("invalid_integer", "Invalid value for dialog_level_enum invalid_integer"),
|
||||
(None, "Missing value for dialog_level_enum"),
|
||||
],
|
||||
)
|
||||
async def test_select_dialog_value_error(
|
||||
hass: HomeAssistant,
|
||||
async_setup_sonos,
|
||||
soco,
|
||||
entity_registry: er.EntityRegistry,
|
||||
speaker_info: dict[str, str],
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
value: str | None,
|
||||
result: str,
|
||||
) -> None:
|
||||
"""Test receiving a value from Sonos that is not convertible to an integer."""
|
||||
|
||||
speaker_info["model_name"] = MODEL_SONOS_ARC_ULTRA.lower()
|
||||
soco.get_speaker_info.return_value = speaker_info
|
||||
soco.dialog_level = value
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
await async_setup_sonos()
|
||||
assert result in caplog.text
|
||||
|
||||
assert SELECT_DIALOG_LEVEL_ENTITY not in entity_registry.entities
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("result", "option"),
|
||||
[
|
||||
@@ -149,12 +179,12 @@ async def test_select_dialog_level_event(
|
||||
|
||||
speaker_info["model_name"] = MODEL_SONOS_ARC_ULTRA.lower()
|
||||
soco.get_speaker_info.return_value = speaker_info
|
||||
soco.dialog_level = 0
|
||||
soco.dialog_level = "0"
|
||||
|
||||
await async_setup_sonos()
|
||||
|
||||
event = create_rendering_control_event(soco)
|
||||
event.variables[ATTR_DIALOG_LEVEL] = 3
|
||||
event.variables[ATTR_DIALOG_LEVEL] = "3"
|
||||
soco.renderingControl.subscribe.return_value._callback(event)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
@@ -175,11 +205,11 @@ async def test_select_dialog_level_poll(
|
||||
|
||||
speaker_info["model_name"] = MODEL_SONOS_ARC_ULTRA.lower()
|
||||
soco.get_speaker_info.return_value = speaker_info
|
||||
soco.dialog_level = 0
|
||||
soco.dialog_level = "0"
|
||||
|
||||
await async_setup_sonos()
|
||||
|
||||
soco.dialog_level = 4
|
||||
soco.dialog_level = "4"
|
||||
|
||||
freezer.tick(SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
|
||||
Reference in New Issue
Block a user