Fix Sonos going offline with 13.3 firmware (#56590)

This commit is contained in:
J. Nick Koston 2021-09-23 22:39:20 -05:00 committed by GitHub
parent 915afedcfc
commit 0363c22dd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 14 additions and 27 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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.", "")

View File

@ -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.

View File

@ -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"},
},

View File

@ -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():