def _create_visible_speakers(self, ip_address: str) -> None: """Create all visible SonosSpeaker instances with the provided seed IP.""" try: soco = SoCo(ip_address) visible_zones = soco.visible_zones self._known_invisible = soco.all_zones - visible_zones except (OSError, SoCoException) as ex: _LOGGER.warning("Failed to request visible zones from %s: %s", ip_address, ex) return for zone in visible_zones: if zone.uid not in self.data.discovered: self._add_speaker(zone)
def _create_soco(self, ip_address: str, source: SoCoCreationSource) -> SoCo | None: """Create a soco instance and return if successful.""" if ip_address in self.data.discovery_ignored: return None try: soco = SoCo(ip_address) # Ensure that the player is available and UID is cached uid = soco.uid _ = soco.volume return soco except NotSupportedException as exc: _LOGGER.debug("Device %s is not supported, ignoring: %s", uid, exc) self.data.discovery_ignored.add(ip_address) except (OSError, SoCoException) as ex: _LOGGER.warning("Failed to connect to %s player '%s': %s", source.value, ip_address, ex) return None
def _poll_manual_hosts(self, now: datetime.datetime | None = None) -> None: """Add and maintain Sonos devices from a manual configuration.""" for host in self.hosts: ip_addr = socket.gethostbyname(host) soco = SoCo(ip_addr) try: visible_zones = soco.visible_zones except OSError: _LOGGER.warning("Could not get visible Sonos devices from %s", ip_addr) else: if new_hosts := { x.ip_address for x in visible_zones if x.ip_address not in self.hosts }: _LOGGER.debug("Adding to manual hosts: %s", new_hosts) self.hosts.update(new_hosts) dispatcher_send( self.hass, f"{SONOS_SPEAKER_ACTIVITY}-{soco.uid}", "manual zone scan", ) break
async def _async_handle_discovery_message(self, uid: str, discovered_ip: str, boot_seqnum: int) -> None: """Handle discovered player creation and activity.""" async with self.discovery_lock: if not self.data.discovered: # Initial discovery, attempt to add all visible zones await self.hass.async_add_executor_job( self._create_visible_speakers, discovered_ip, ) elif uid not in self.data.discovered: if self.is_device_invisible(discovered_ip): return await self.hass.async_add_executor_job(self._add_speaker, SoCo(discovered_ip)) elif boot_seqnum and boot_seqnum > self.data.boot_counts[uid]: self.data.boot_counts[uid] = boot_seqnum async_dispatcher_send(self.hass, f"{SONOS_REBOOTED}-{uid}") else: async_dispatcher_send(self.hass, f"{SONOS_SPEAKER_ACTIVITY}-{uid}", "discovery")
#!/usr/bin/env python import status_wrapper from soco.core import SoCo sonos = SoCo("10.0.0.11") def wrap(j): # Truncate music titles j[1]["short_text"] = j[1]["full_text"][:160] + "..." try: block = {"name": "sonos"} volume = sonos.volume mute = sonos.mute icon = "♫" if mute: icon = "✕" block["color"] = status_wrapper.color_degraded block["full_text"] = "{} {}%".format(icon, volume) j.insert(0, block) except: pass return j status_wrapper.mainloop(wrap)