diff --git a/homeassistant/components/sonos/number.py b/homeassistant/components/sonos/number.py index 202df1cb6f1..3b034423471 100644 --- a/homeassistant/components/sonos/number.py +++ b/homeassistant/components/sonos/number.py @@ -20,6 +20,8 @@ LEVEL_TYPES = { "bass": (-10, 10), "treble": (-10, 10), "sub_gain": (-15, 15), + "surround_level": (-15, 15), + "music_surround_level": (-15, 15), } _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sonos/speaker.py b/homeassistant/components/sonos/speaker.py index f9decf1c27e..93d0afbcf9c 100644 --- a/homeassistant/components/sonos/speaker.py +++ b/homeassistant/components/sonos/speaker.py @@ -146,6 +146,9 @@ class SonosSpeaker: self.sub_enabled: bool | None = None self.sub_gain: int | None = None self.surround_enabled: bool | None = None + self.surround_mode: bool | None = None + self.surround_level: int | None = None + self.music_surround_level: int | None = None # Misc features self.buttons_enabled: bool | None = None @@ -515,11 +518,19 @@ class SonosSpeaker: "night_mode", "sub_enabled", "surround_enabled", + "surround_mode", ): if bool_var in variables: setattr(self, bool_var, variables[bool_var] == "1") - for int_var in ("audio_delay", "bass", "treble", "sub_gain"): + for int_var in ( + "audio_delay", + "bass", + "treble", + "sub_gain", + "surround_level", + "music_surround_level", + ): if int_var in variables: setattr(self, int_var, variables[int_var]) diff --git a/homeassistant/components/sonos/switch.py b/homeassistant/components/sonos/switch.py index 29abb097df7..53911d85d3e 100644 --- a/homeassistant/components/sonos/switch.py +++ b/homeassistant/components/sonos/switch.py @@ -39,6 +39,7 @@ ATTR_INCLUDE_LINKED_ZONES = "include_linked_zones" ATTR_CROSSFADE = "cross_fade" ATTR_LOUDNESS = "loudness" +ATTR_MUSIC_PLAYBACK_FULL_VOLUME = "surround_mode" ATTR_NIGHT_SOUND = "night_mode" ATTR_SPEECH_ENHANCEMENT = "dialog_level" ATTR_STATUS_LIGHT = "status_light" @@ -50,6 +51,7 @@ ALL_FEATURES = ( ATTR_TOUCH_CONTROLS, ATTR_CROSSFADE, ATTR_LOUDNESS, + ATTR_MUSIC_PLAYBACK_FULL_VOLUME, ATTR_NIGHT_SOUND, ATTR_SPEECH_ENHANCEMENT, ATTR_SUB_ENABLED, @@ -67,6 +69,7 @@ POLL_REQUIRED = ( FRIENDLY_NAMES = { ATTR_CROSSFADE: "Crossfade", ATTR_LOUDNESS: "Loudness", + ATTR_MUSIC_PLAYBACK_FULL_VOLUME: "Surround Music Full Volume", ATTR_NIGHT_SOUND: "Night Sound", ATTR_SPEECH_ENHANCEMENT: "Speech Enhancement", ATTR_STATUS_LIGHT: "Status Light", @@ -77,6 +80,7 @@ FRIENDLY_NAMES = { FEATURE_ICONS = { ATTR_LOUDNESS: "mdi:bullhorn-variant", + ATTR_MUSIC_PLAYBACK_FULL_VOLUME: "mdi:music-note-plus", ATTR_NIGHT_SOUND: "mdi:chat-sleep", ATTR_SPEECH_ENHANCEMENT: "mdi:ear-hearing", ATTR_CROSSFADE: "mdi:swap-horizontal", diff --git a/tests/components/sonos/conftest.py b/tests/components/sonos/conftest.py index d493c9d50c9..f776fb62d58 100644 --- a/tests/components/sonos/conftest.py +++ b/tests/components/sonos/conftest.py @@ -117,6 +117,9 @@ def soco_fixture( mock_soco.sub_enabled = False mock_soco.sub_gain = 5 mock_soco.surround_enabled = True + mock_soco.surround_mode = True + mock_soco.surround_level = 3 + mock_soco.music_surround_level = 4 mock_soco.soundbar_audio_input_format = "Dolby 5.1" mock_soco.get_battery_info.return_value = battery_info mock_soco.all_zones = {mock_soco} diff --git a/tests/components/sonos/test_number.py b/tests/components/sonos/test_number.py index 5829a7a6724..83dcdf78ff8 100644 --- a/tests/components/sonos/test_number.py +++ b/tests/components/sonos/test_number.py @@ -22,6 +22,16 @@ async def test_number_entities(hass, async_autosetup_sonos, soco): audio_delay_state = hass.states.get(audio_delay_number.entity_id) assert audio_delay_state.state == "2" + surround_level_number = entity_registry.entities["number.zone_a_surround_level"] + surround_level_state = hass.states.get(surround_level_number.entity_id) + assert surround_level_state.state == "3" + + music_surround_level_number = entity_registry.entities[ + "number.zone_a_music_surround_level" + ] + music_surround_level_state = hass.states.get(music_surround_level_number.entity_id) + assert music_surround_level_state.state == "4" + with patch("soco.SoCo.audio_delay") as mock_audio_delay: await hass.services.async_call( NUMBER_DOMAIN, diff --git a/tests/components/sonos/test_switch.py b/tests/components/sonos/test_switch.py index f224a1e187e..2b794657565 100644 --- a/tests/components/sonos/test_switch.py +++ b/tests/components/sonos/test_switch.py @@ -52,6 +52,14 @@ async def test_switch_attributes(hass, async_autosetup_sonos, soco): assert alarm_state.attributes.get(ATTR_PLAY_MODE) == "SHUFFLE_NOREPEAT" assert not alarm_state.attributes.get(ATTR_INCLUDE_LINKED_ZONES) + surround_music_full_volume = entity_registry.entities[ + "switch.zone_a_surround_music_full_volume" + ] + surround_music_full_volume_state = hass.states.get( + surround_music_full_volume.entity_id + ) + assert surround_music_full_volume_state.state == STATE_ON + night_sound = entity_registry.entities["switch.zone_a_night_sound"] night_sound_state = hass.states.get(night_sound.entity_id) assert night_sound_state.state == STATE_ON