mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Fix Sonos going offline with 13.3 firmware (#56590)
This commit is contained in:
parent
915afedcfc
commit
0363c22dd8
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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.", "")
|
||||
|
@ -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.
|
||||
|
@ -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"},
|
||||
},
|
||||
|
@ -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():
|
||||
|
Loading…
x
Reference in New Issue
Block a user