diff --git a/homeassistant/components/sonos/__init__.py b/homeassistant/components/sonos/__init__.py index 6650e5f8904..aafcba744ea 100644 --- a/homeassistant/components/sonos/__init__.py +++ b/homeassistant/components/sonos/__init__.py @@ -90,6 +90,7 @@ class SonosData: self.discovery_ignored: set[str] = set() self.discovery_known: set[str] = set() self.boot_counts: dict[str, int] = {} + self.mdns_names: dict[str, str] = {} async def async_setup(hass, config): @@ -273,12 +274,12 @@ class SonosDiscoveryManager: if uid.startswith("uuid:"): uid = uid[5:] self.async_discovered_player( - "SSDP", info, discovered_ip, uid, boot_seqnum, info.get("modelName") + "SSDP", info, discovered_ip, uid, boot_seqnum, info.get("modelName"), None ) @callback def async_discovered_player( - self, source, info, discovered_ip, uid, boot_seqnum, model + self, source, info, discovered_ip, uid, boot_seqnum, model, mdns_name ): """Handle discovery via ssdp or zeroconf.""" if model in DISCOVERY_IGNORED_MODELS: @@ -287,6 +288,9 @@ class SonosDiscoveryManager: if boot_seqnum: boot_seqnum = int(boot_seqnum) self.data.boot_counts.setdefault(uid, boot_seqnum) + if mdns_name: + self.data.mdns_names[uid] = mdns_name + if uid not in self.data.discovery_known: _LOGGER.debug("New %s discovery uid=%s: %s", source, uid, info) self.data.discovery_known.add(uid) diff --git a/homeassistant/components/sonos/config_flow.py b/homeassistant/components/sonos/config_flow.py index 3bbdf2d9a26..3fa3bbb8fa8 100644 --- a/homeassistant/components/sonos/config_flow.py +++ b/homeassistant/components/sonos/config_flow.py @@ -4,7 +4,7 @@ import logging import soco from homeassistant import config_entries -from homeassistant.const import CONF_HOST +from homeassistant.const import CONF_HOST, CONF_NAME from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers.config_entry_flow import DiscoveryFlowHandler @@ -38,13 +38,14 @@ class SonosDiscoveryFlowHandler(DiscoveryFlowHandler): 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] + mdns_name = discovery_info[CONF_NAME] properties = discovery_info["properties"] boot_seqnum = properties.get("bootseq") model = properties.get("model") uid = hostname_to_uid(hostname) if discovery_manager := self.hass.data.get(DATA_SONOS_DISCOVERY_MANAGER): discovery_manager.async_discovered_player( - "Zeroconf", properties, host, uid, boot_seqnum, model + "Zeroconf", properties, host, uid, boot_seqnum, model, mdns_name ) return await self.async_step_discovery(discovery_info) diff --git a/homeassistant/components/sonos/helpers.py b/homeassistant/components/sonos/helpers.py index 0854361cd79..2e5b3a8c032 100644 --- a/homeassistant/components/sonos/helpers.py +++ b/homeassistant/components/sonos/helpers.py @@ -41,16 +41,6 @@ def soco_error(errorcodes: list[str] | None = None) -> Callable: return decorator -def uid_to_short_hostname(uid: str) -> str: - """Convert a Sonos uid to a short hostname.""" - hostname_uid = uid - if hostname_uid.startswith(UID_PREFIX): - hostname_uid = hostname_uid[len(UID_PREFIX) :] - if hostname_uid.endswith(UID_POSTFIX): - hostname_uid = hostname_uid[: -len(UID_POSTFIX)] - return f"Sonos-{hostname_uid}" - - def hostname_to_uid(hostname: str) -> str: """Convert a Sonos hostname to a uid.""" baseuid = hostname.split("-")[1].replace(".local.", "") diff --git a/homeassistant/components/sonos/speaker.py b/homeassistant/components/sonos/speaker.py index 744850380bc..35331dec051 100644 --- a/homeassistant/components/sonos/speaker.py +++ b/homeassistant/components/sonos/speaker.py @@ -59,7 +59,7 @@ from .const import ( SUBSCRIPTION_TIMEOUT, ) from .favorites import SonosFavorites -from .helpers import soco_error, uid_to_short_hostname +from .helpers import soco_error EVENT_CHARGING = { "CHARGING": True, @@ -524,11 +524,10 @@ class SonosSpeaker: self, callback_timestamp: datetime.datetime | None = None ) -> None: """Make this player unavailable when it was not seen recently.""" - if callback_timestamp: + data = self.hass.data[DATA_SONOS] + if callback_timestamp and (zcname := data.mdns_names.get(self.soco.uid)): # Called by a _seen_timer timeout, check mDNS one more time # This should not be checked in an "active" unseen scenario - hostname = uid_to_short_hostname(self.soco.uid) - zcname = f"{hostname}.{MDNS_SERVICE}" aiozeroconf = await zeroconf.async_get_async_instance(self.hass) if await aiozeroconf.async_get_service_info(MDNS_SERVICE, zcname): # We can still see the speaker via zeroconf check again later. diff --git a/tests/components/sonos/test_config_flow.py b/tests/components/sonos/test_config_flow.py index 90ffdb155ea..faf4e07ac9c 100644 --- a/tests/components/sonos/test_config_flow.py +++ b/tests/components/sonos/test_config_flow.py @@ -45,6 +45,7 @@ async def test_zeroconf_form(hass: core.HomeAssistant): context={"source": config_entries.SOURCE_ZEROCONF}, data={ "host": "192.168.4.2", + "name": "Sonos-aaa@Living Room._sonos._tcp.local.", "hostname": "Sonos-aaa", "properties": {"bootseq": "1234"}, }, diff --git a/tests/components/sonos/test_helpers.py b/tests/components/sonos/test_helpers.py index 858657e01c0..a52337f9455 100644 --- a/tests/components/sonos/test_helpers.py +++ b/tests/components/sonos/test_helpers.py @@ -1,15 +1,7 @@ """Test the sonos config flow.""" from __future__ import annotations -from homeassistant.components.sonos.helpers import ( - hostname_to_uid, - uid_to_short_hostname, -) - - -async def test_uid_to_short_hostname(): - """Test we can convert a uid to a short hostname.""" - assert uid_to_short_hostname("RINCON_347E5C0CF1E301400") == "Sonos-347E5C0CF1E3" +from homeassistant.components.sonos.helpers import hostname_to_uid async def test_uid_to_hostname():