1
mirror of https://github.com/home-assistant/core synced 2024-08-28 03:36:46 +02:00

Add subwoofer crossover support to Sonos Amp devices (#106290)

This commit is contained in:
jjlawren 2023-12-23 04:25:20 -05:00 committed by GitHub
parent 5d2ddcb1d2
commit 0ae4d017b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 21 deletions

View File

@ -21,6 +21,7 @@ LEVEL_TYPES = {
"bass": (-10, 10),
"balance": (-100, 100),
"treble": (-10, 10),
"sub_crossover": (50, 110),
"sub_gain": (-15, 15),
"surround_level": (-15, 15),
"music_surround_level": (-15, 15),

View File

@ -154,6 +154,7 @@ class SonosSpeaker:
self.dialog_level: bool | None = None
self.night_mode: bool | None = None
self.sub_enabled: bool | None = None
self.sub_crossover: int | None = None
self.sub_gain: int | None = None
self.surround_enabled: bool | None = None
self.surround_mode: bool | None = None
@ -561,6 +562,7 @@ class SonosSpeaker:
"audio_delay",
"bass",
"treble",
"sub_crossover",
"sub_gain",
"surround_level",
"music_surround_level",

View File

@ -36,6 +36,9 @@
"treble": {
"name": "Treble"
},
"sub_crossover": {
"name": "Sub crossover frequency"
},
"sub_gain": {
"name": "Sub gain"
},

View File

@ -108,8 +108,26 @@ def config_entry_fixture():
class MockSoCo(MagicMock):
"""Mock the Soco Object."""
uid = "RINCON_test"
play_mode = "NORMAL"
mute = False
night_mode = True
dialog_level = True
loudness = True
volume = 19
audio_delay = 2
balance = (61, 100)
bass = 1
treble = -1
mic_enabled = False
sub_crossover = None # Default to None for non-Amp devices
sub_enabled = False
sub_gain = 5
surround_enabled = True
surround_mode = True
surround_level = 3
music_surround_level = 4
soundbar_audio_input_format = "Dolby 5.1"
@property
def visible_zones(self):
@ -143,10 +161,7 @@ class SoCoMockFactory:
mock_soco.mock_add_spec(SoCo)
mock_soco.ip_address = ip_address
if ip_address != "192.168.42.2":
mock_soco.uid = f"RINCON_test_{ip_address}"
else:
mock_soco.uid = "RINCON_test"
mock_soco.play_mode = "NORMAL"
mock_soco.uid += f"_{ip_address}"
mock_soco.music_library = self.music_library
mock_soco.get_current_track_info.return_value = self.current_track_info
mock_soco.music_source_from_uri = SoCo.music_source_from_uri
@ -161,23 +176,6 @@ class SoCoMockFactory:
mock_soco.contentDirectory = SonosMockService("ContentDirectory", ip_address)
mock_soco.deviceProperties = SonosMockService("DeviceProperties", ip_address)
mock_soco.alarmClock = self.alarm_clock
mock_soco.mute = False
mock_soco.night_mode = True
mock_soco.dialog_level = True
mock_soco.loudness = True
mock_soco.volume = 19
mock_soco.audio_delay = 2
mock_soco.balance = (61, 100)
mock_soco.bass = 1
mock_soco.treble = -1
mock_soco.mic_enabled = False
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 = self.battery_info
mock_soco.all_zones = {mock_soco}
mock_soco.group.coordinator = mock_soco

View File

@ -6,6 +6,8 @@ from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
CROSSOVER_ENTITY = "number.zone_a_sub_crossover_frequency"
async def test_number_entities(
hass: HomeAssistant, async_autosetup_sonos, soco, entity_registry: er.EntityRegistry
@ -62,3 +64,32 @@ async def test_number_entities(
blocking=True,
)
mock_sub_gain.assert_called_once_with(-8)
# sub_crossover is only available on Sonos Amp devices, see test_amp_number_entities
assert CROSSOVER_ENTITY not in entity_registry.entities
async def test_amp_number_entities(
hass: HomeAssistant, async_setup_sonos, soco, entity_registry: er.EntityRegistry
) -> None:
"""Test the sub_crossover feature only available on Sonos Amp devices.
The sub_crossover value will be None on all other device types.
"""
with patch.object(soco, "sub_crossover", 50):
await async_setup_sonos()
sub_crossover_number = entity_registry.entities[CROSSOVER_ENTITY]
sub_crossover_state = hass.states.get(sub_crossover_number.entity_id)
assert sub_crossover_state.state == "50"
with patch.object(
type(soco), "sub_crossover", new_callable=PropertyMock
) as mock_sub_crossover:
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{ATTR_ENTITY_ID: sub_crossover_number.entity_id, "value": 110},
blocking=True,
)
mock_sub_crossover.assert_called_once_with(110)