Improve Sonos diagnostics (#64586)

This commit is contained in:
jjlawren 2022-01-20 17:14:08 -06:00 committed by GitHub
parent 3792b8b3ca
commit e7f0962979
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 25 deletions

View File

@ -21,20 +21,24 @@ MEDIA_DIAGNOSTIC_ATTRIBUTES = (
"source_name", "source_name",
"title", "title",
"uri", "uri",
"_last_event_variables",
) )
SPEAKER_DIAGNOSTIC_ATTRIBUTES = ( SPEAKER_DIAGNOSTIC_ATTRIBUTES = (
"available", "available",
"battery_info", "battery_info",
"hardware_version",
"household_id", "household_id",
"is_coordinator", "is_coordinator",
"model_name", "model_name",
"model_number",
"software_version",
"sonos_group_entities", "sonos_group_entities",
"subscription_address", "subscription_address",
"subscriptions_failed", "subscriptions_failed",
"version",
"zone_name", "zone_name",
"_group_members_missing", "_group_members_missing",
"_last_activity", "_last_activity",
"_last_event_cache",
) )
@ -52,8 +56,7 @@ async def async_get_config_entry_diagnostics(
continue continue
for key, value in data.items(): for key, value in data.items():
if isinstance(value, SonosSpeaker): if isinstance(value, SonosSpeaker):
speaker_info = await async_generate_speaker_info(hass, value) payload[section][key] = await async_generate_speaker_info(hass, value)
payload[section][key] = speaker_info
else: else:
payload[section][key] = value payload[section][key] = value
@ -66,21 +69,8 @@ async def async_generate_media_info(
"""Generate a diagnostic payload for current media metadata.""" """Generate a diagnostic payload for current media metadata."""
payload = {} payload = {}
def get_contents(item):
if isinstance(item, (int, float, str)):
return item
if isinstance(item, dict):
payload = {}
for key, value in item.items():
payload[key] = get_contents(value)
return payload
if hasattr(item, "__dict__"):
return vars(item)
return item
for attrib in MEDIA_DIAGNOSTIC_ATTRIBUTES: for attrib in MEDIA_DIAGNOSTIC_ATTRIBUTES:
value = getattr(speaker.media, attrib) payload[attrib] = getattr(speaker.media, attrib)
payload[attrib] = get_contents(value)
def poll_current_track_info(): def poll_current_track_info():
return speaker.soco.avTransport.GetPositionInfo( return speaker.soco.avTransport.GetPositionInfo(
@ -99,7 +89,22 @@ async def async_generate_speaker_info(
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Generate the diagnostic payload for a specific speaker.""" """Generate the diagnostic payload for a specific speaker."""
payload = {} payload = {}
def get_contents(item):
if isinstance(item, (int, float, str)):
return item
if isinstance(item, dict):
payload = {}
for key, value in item.items():
payload[key] = get_contents(value)
return payload
if hasattr(item, "__dict__"):
return vars(item)
return item
for attrib in SPEAKER_DIAGNOSTIC_ATTRIBUTES: for attrib in SPEAKER_DIAGNOSTIC_ATTRIBUTES:
payload[attrib] = getattr(speaker, attrib) value = getattr(speaker, attrib)
payload[attrib] = get_contents(value)
payload["media"] = await async_generate_media_info(hass, speaker) payload["media"] = await async_generate_media_info(hass, speaker)
return payload return payload

View File

@ -123,7 +123,6 @@ class SonosMedia:
self.position: float | None = None self.position: float | None = None
self.position_updated_at: datetime.datetime | None = None self.position_updated_at: datetime.datetime | None = None
self._last_event_variables: dict[str, Any] | None = None
def clear(self) -> None: def clear(self) -> None:
"""Clear basic media info.""" """Clear basic media info."""
@ -164,6 +163,7 @@ class SonosSpeaker:
self._resubscription_lock: asyncio.Lock | None = None self._resubscription_lock: asyncio.Lock | None = None
self._event_dispatchers: dict[str, Callable] = {} self._event_dispatchers: dict[str, Callable] = {}
self._last_activity: float = NEVER_TIME self._last_activity: float = NEVER_TIME
self._last_event_cache: dict[str, Any] = {}
# Scheduled callback handles # Scheduled callback handles
self._poll_timer: Callable | None = None self._poll_timer: Callable | None = None
@ -172,8 +172,11 @@ class SonosSpeaker:
self.dispatchers: list[Callable] = [] self.dispatchers: list[Callable] = []
# Device information # Device information
self.hardware_version = speaker_info["hardware_version"]
self.software_version = speaker_info["software_version"]
self.mac_address = speaker_info["mac_address"] self.mac_address = speaker_info["mac_address"]
self.model_name = speaker_info["model_name"] self.model_name = speaker_info["model_name"]
self.model_number = speaker_info["model_number"]
self.uid = speaker_info["uid"] self.uid = speaker_info["uid"]
self.version = speaker_info["display_version"] self.version = speaker_info["display_version"]
self.zone_name = speaker_info["zone_name"] self.zone_name = speaker_info["zone_name"]
@ -427,6 +430,9 @@ class SonosSpeaker:
dispatcher = self._event_dispatchers[event.service.service_type] dispatcher = self._event_dispatchers[event.service.service_type]
dispatcher(event) dispatcher(event)
# Save most recent event variables for diagnostics
self._last_event_cache[event.service.service_type] = event.variables
@callback @callback
def async_dispatch_alarms(self, event: SonosEvent) -> None: def async_dispatch_alarms(self, event: SonosEvent) -> None:
"""Add the soco instance associated with the event to the callback.""" """Add the soco instance associated with the event to the callback."""
@ -1003,12 +1009,6 @@ class SonosSpeaker:
if new_status == SONOS_STATE_TRANSITIONING: if new_status == SONOS_STATE_TRANSITIONING:
return return
if variables:
# Store for diagnostics
self.media._last_event_variables = ( # pylint: disable=protected-access
variables
)
self.media.clear() self.media.clear()
update_position = new_status != self.media.playback_status update_position = new_status != self.media.playback_status
self.media.playback_status = new_status self.media.playback_status = new_status

View File

@ -206,6 +206,8 @@ def speaker_info_fixture():
"zone_name": "Zone A", "zone_name": "Zone A",
"uid": "RINCON_test", "uid": "RINCON_test",
"model_name": "Model Name", "model_name": "Model Name",
"model_number": "S12",
"hardware_version": "1.20.1.6-1.1",
"software_version": "49.2-64250", "software_version": "49.2-64250",
"mac_address": "00-11-22-33-44-55", "mac_address": "00-11-22-33-44-55",
"display_version": "13.1", "display_version": "13.1",