예제 #1
0
    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)
예제 #2
0
    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
예제 #3
0
 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
예제 #4
0
 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")
예제 #5
0
#!/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)