From cab9f821a1dfc3c80096ad3c60aab5b9f08ee2ab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 11 Nov 2021 00:31:08 -0600 Subject: [PATCH] Fix zeroconf with sonos v1 firmware (#59460) --- homeassistant/components/sonos/config_flow.py | 2 +- homeassistant/components/sonos/helpers.py | 7 ++- tests/components/sonos/test_config_flow.py | 50 +++++++++++++++++++ tests/components/sonos/test_helpers.py | 6 +++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sonos/config_flow.py b/homeassistant/components/sonos/config_flow.py index 745d3db3890..98e1194ebd0 100644 --- a/homeassistant/components/sonos/config_flow.py +++ b/homeassistant/components/sonos/config_flow.py @@ -30,7 +30,7 @@ class SonosDiscoveryFlowHandler(DiscoveryFlowHandler): ) -> FlowResult: """Handle a flow initialized by zeroconf.""" hostname = discovery_info["hostname"] - if hostname is None or not hostname.startswith("Sonos-"): + if hostname is None or not hostname.lower().startswith("sonos"): return self.async_abort(reason="not_sonos_device") await self.async_set_unique_id(self._domain, raise_on_progress=False) host = discovery_info[CONF_HOST] diff --git a/homeassistant/components/sonos/helpers.py b/homeassistant/components/sonos/helpers.py index 01a75eb7747..490bcdefba5 100644 --- a/homeassistant/components/sonos/helpers.py +++ b/homeassistant/components/sonos/helpers.py @@ -44,5 +44,10 @@ def soco_error(errorcodes: list[str] | None = None) -> Callable: def hostname_to_uid(hostname: str) -> str: """Convert a Sonos hostname to a uid.""" - baseuid = hostname.split("-")[1].replace(".local.", "") + if hostname.startswith("Sonos-"): + baseuid = hostname.split("-")[1].replace(".local.", "") + elif hostname.startswith("sonos"): + baseuid = hostname[5:].replace(".local.", "") + else: + raise ValueError(f"{hostname} is not a sonos device.") return f"{UID_PREFIX}{baseuid}{UID_POSTFIX}" diff --git a/tests/components/sonos/test_config_flow.py b/tests/components/sonos/test_config_flow.py index 39f3966e2ce..7d6fd02f51d 100644 --- a/tests/components/sonos/test_config_flow.py +++ b/tests/components/sonos/test_config_flow.py @@ -75,6 +75,56 @@ async def test_zeroconf_form(hass: core.HomeAssistant): assert len(mock_manager.mock_calls) == 2 +async def test_zeroconf_sonos_v1(hass: core.HomeAssistant): + """Test we pass sonos devices to the discovery manager with v1 firmware devices.""" + + mock_manager = hass.data[DATA_SONOS_DISCOVERY_MANAGER] = MagicMock() + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_ZEROCONF}, + data={ + "host": "192.168.1.107", + "port": 1443, + "hostname": "sonos5CAAFDE47AC8.local.", + "type": "_sonos._tcp.local.", + "name": "Sonos-5CAAFDE47AC8._sonos._tcp.local.", + "properties": { + "_raw": { + "info": b"/api/v1/players/RINCON_5CAAFDE47AC801400/info", + "vers": b"1", + "protovers": b"1.18.9", + }, + "info": "/api/v1/players/RINCON_5CAAFDE47AC801400/info", + "vers": "1", + "protovers": "1.18.9", + }, + }, + ) + assert result["type"] == "form" + assert result["errors"] is None + + with patch( + "homeassistant.components.sonos.async_setup", + return_value=True, + ) as mock_setup, patch( + "homeassistant.components.sonos.async_setup_entry", + return_value=True, + ) as mock_setup_entry: + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], + {}, + ) + await hass.async_block_till_done() + + assert result2["type"] == "create_entry" + assert result2["title"] == "Sonos" + assert result2["data"] == {} + + assert len(mock_setup.mock_calls) == 1 + assert len(mock_setup_entry.mock_calls) == 1 + assert len(mock_manager.mock_calls) == 2 + + async def test_zeroconf_form_not_sonos(hass: core.HomeAssistant): """Test we abort on non-sonos devices.""" mock_manager = hass.data[DATA_SONOS_DISCOVERY_MANAGER] = MagicMock() diff --git a/tests/components/sonos/test_helpers.py b/tests/components/sonos/test_helpers.py index a52337f9455..be32d3a190b 100644 --- a/tests/components/sonos/test_helpers.py +++ b/tests/components/sonos/test_helpers.py @@ -1,9 +1,15 @@ """Test the sonos config flow.""" from __future__ import annotations +import pytest + from homeassistant.components.sonos.helpers import hostname_to_uid async def test_uid_to_hostname(): """Test we can convert a hostname to a uid.""" assert hostname_to_uid("Sonos-347E5C0CF1E3.local.") == "RINCON_347E5C0CF1E301400" + assert hostname_to_uid("sonos5CAAFDE47AC8.local.") == "RINCON_5CAAFDE47AC801400" + + with pytest.raises(ValueError): + assert hostname_to_uid("notsonos5CAAFDE47AC8.local.") -- GitLab