Exemple #1
0
def detect_devices():
    # Uses ssdp to return a list of Sky boxes on the network.  Uses the netdisco package to do the discovery.
    ssdp_entries = scan()

    # initialise dictionary for founfd Sky devices
    found_entries = {}

    address_regex = re.compile(r'https*://([\w\.]*):([0-9]+)/.*', re.X)

    type_regex = re.compile(r'.*:(\w*Sky\w*):.*', re.X)

    for entry in ssdp_entries:

        # is it a sky device
        st = entry.st

        if "schemas-nds-com" in st and "Sky" in st:
            m = address_regex.match(entry.location)
            addr = m.group(1)
            m = type_regex.match(st)
            type = m.group(1)

            this_remote = found_entries.get(addr, SkyRemote(addr))
            this_remote.addSDPEntry(type, entry)
            found_entries[addr] = this_remote

    return found_entries.values()
Exemple #2
0
def discover(timeout=5):
    """
    Convenience method to discover UPnP devices on the network. Returns a
    list of `upnp.Device` instances. Any invalid servers are silently
    ignored.
    """
    devices = {}
    for entry in scan(timeout):
        if entry.location in devices:
            continue
        try:
            devices[entry.location] = Device(entry.location)
        except Exception as exc:
            log = _getLogger("ssdp")
            log.error('Error \'%s\' for %s', exc, entry.location)
    return list(devices.values())
Exemple #3
0
 def discoverSSDP(self, timeout=5):
     upnp_ports = [None] * len(self._urns)
     upnp_paths = [None] * len(self._urns)
     for entry in scan(timeout):
         if entry.location.startswith('http://{}'.format(
                 self._config['host'])):
             for i in range(len(self._urns)):
                 if entry.st == self._urns[i]:
                     upnp_ports[i] = int(
                         entry.location.split(':')[2].split('/')[0])
                     upnp_paths[i] = self.getPathFromUrlSsdp(
                         entry.location, i)
             if None not in upnp_paths:
                 for i in range(len(self._urns)):
                     _LOGGER.info(
                         '{} uPNP service detected in http://{}{}'.format(
                             self._urns[i].split(':')[3],
                             entry.location.split('/')[2], upnp_paths[i]))
                 return tuple(upnp_ports), tuple(upnp_paths)
     return None, None
Exemple #4
0
    def discover_upnp(username=None):
        from netdisco.ssdp import scan

        PHILIPS = 'Royal Philips Electronics'
        BRIDGE_MODELS = ['929000226503', 'BSB002']

        hue_bridges = []
        res = scan()

        for h in res:
            _LOGGER.info('Check {}'.format(h))
            device_info = h.description.get('device', None)
            if device_info:
                manufacturer = device_info.get('manufacturer', None)
                model = device_info.get('modelNumber', None)
                if manufacturer == PHILIPS and model in BRIDGE_MODELS:
                    url = h.description['URLBase']
                    if url not in hue_bridges:
                        hue_bridges.append(url)
            else:
                _LOGGER.error('Missing device info')
        return [Bridge.from_url(x, username) for x in hue_bridges]
    def update(self):
        """Get the latest player details from the device."""
        import upnpclient
        from netdisco.ssdp import scan

        if self._slave_mode:
            return True

        if self._upnp_device is None:
            for entry in scan(UPNP_TIMEOUT):
                try:
                    if upnpclient.Device(entry.location).friendly_name == \
                            self._name:
                        self._upnp_device = upnpclient.Device(entry.location)
                        break
                except requests.exceptions.HTTPError:
                    pass

        self._lpapi.call('GET', 'getPlayerStatus')
        player_api_result = self._lpapi.data

        if player_api_result is None:
            self._media_title = 'Unable to connect to device'
            return True

        try:
            player_status = json.loads(player_api_result)
        except ValueError:
            _LOGGER.warning("REST result could not be parsed as JSON")
            _LOGGER.debug("Erroneous JSON: %s", player_api_result)
            player_status = None

        if isinstance(player_status, dict):
            self._lpapi.call('GET', 'getStatus')
            device_api_result = self._lpapi.data
            try:
                device_status = json.loads(device_api_result)
            except ValueError:
                _LOGGER.warning("REST result could not be parsed as JSON")
                _LOGGER.debug("Erroneous JSON: %s", device_api_result)
            if isinstance(device_status, dict):
                self._wifi_channel = device_status['WifiChannel']
                self._ssid = \
                    binascii.hexlify(device_status['ssid'].encode('utf-8'))
                self._ssid = self._ssid.decode()

            # Update variables that changes during playback of a track.
            self._volume = player_status['vol']
            self._muted = player_status['mute']
            self._seek_position = int(int(player_status['curpos']) / 1000)
            self._position_updated_at = utcnow()
            self._media_uri = str(bytearray.fromhex(
                player_status['iuri']).decode())
            self._state = {
                'stop': STATE_PAUSED,
                'play': STATE_PLAYING,
                'pause': STATE_PAUSED,
            }.get(player_status['status'], STATE_UNKNOWN)
            self._source = SOURCES_MAP.get(player_status['mode'],
                                           'WiFi')
            self._sound_mode = SOUND_MODES.get(player_status['eq'])
            self._shuffle = True if player_status['loop'] == '2' else False
            self._playing_spotify = bool(player_status['mode'] == '31')

            if self._is_playing_new_track(player_status):
                # Only do some things when a new track is playing.
                if self._playing_spotify or player_status['totlen'] == '0':
                    self._update_via_upnp()

                else:
                    self._update_from_id3()
                    if self._lfmapi is not None and\
                            self._media_title is not None:
                        self._get_lastfm_coverart()
                    else:
                        self._media_image_url = None

            self._duration = int(int(player_status['totlen']) / 1000)

        else:
            _LOGGER.warning("JSON result was not a dictionary")

        # Get  multiroom slave information
        self._lpapi.call('GET', 'multiroom:getSlaveList')
        slave_list = self._lpapi.data

        try:
            slave_list = json.loads(slave_list)
        except ValueError:
            _LOGGER.warning("REST result could not be parsed as JSON")
            _LOGGER.debug("Erroneous JSON: %s", slave_list)

        self._slave_list = []
        if isinstance(slave_list, dict):
            if int(slave_list['slaves']) > 0:
                slave_list = slave_list['slave_list']
                for slave in slave_list:
                    device = self.hass.data[DATA_LINKPLAY].get(slave['name'],
                                                               None)
                    if device:
                        self._slave_list.append(device)
                        device.set_master(self)
                        device.set_slave_mode(True)
                        device.set_media_title("Slave mode")
                        device.set_media_artist(self.name)
                        device.set_volume(slave['volume'])
                        device.set_muted(slave['mute'])
                        device.set_state(self.state)
                        device.set_slave_ip(slave['ip'])
                        device.set_seek_position(self.media_position)
                        device.set_duration(self.media_duration)
                        device.set_position_updated_at(
                            self.media_position_updated_at)
                        device.set_source(self._source)
                        device.set_sound_mode(self._sound_mode)
        else:
            _LOGGER.warning("JSON result was not a dictionary")

        return True
Exemple #6
0
def _run_ssdp_scans():
    _LOGGER.debug("Scanning")
    # Run 3 times as packets can get lost
    return itertools.chain.from_iterable([ssdp.scan() for _ in range(3)])