def find(self, speaker_name, require_visible=True): """Find a speaker by name and return its SoCo object.""" speaker_names = set() return_speaker = None for speaker in self._speakers: if require_visible and not speaker.is_visible: continue match, exact = speaker_name_matches(speaker_name, speaker.speaker_name) if match and exact: speaker_names.add(speaker.speaker_name) return soco.SoCo(speaker.ip_address) if match and not exact: speaker_names.add(speaker.speaker_name) if not return_speaker: return_speaker = soco.SoCo(speaker.ip_address) if len(speaker_names) > 1: print("Speaker name '{}' is ambiguous within {}".format( speaker_name, speaker_names)) return None return return_speaker
def find(self, speaker_name, require_visible=True): """Find a speaker by name and return its SoCo object.""" # Normalise apostrophes speaker_name = speaker_name.replace("’", "'") # Check for exact match first for speaker in self._speakers: # Normalise apostrophes s = speaker.speaker_name.replace("’", "'") if speaker_name == s: if require_visible: if speaker.is_visible: logging.info( "Found exact speaker name match for '{}'".format( speaker.speaker_name ) ) return soco.SoCo(speaker.ip_address) else: return soco.SoCo(speaker.ip_address) # Check for partial, case insensitive match if no exact match for speaker in self._speakers: # Normalise apostrophes s = speaker.speaker_name.replace("’", "'") if speaker_name.lower() in s.lower(): if require_visible: if speaker.is_visible: logging.info( "Found fuzzy speaker name match for '{}'".format( speaker.speaker_name ) ) return soco.SoCo(speaker.ip_address) else: return soco.SoCo(speaker.ip_address) return None
def setup_platform(hass, config, add_devices, discovery_info=None): """ Sets up the Sonos platform. """ import soco import socket if discovery_info: add_devices([SonosDevice(hass, soco.SoCo(discovery_info))]) return True players = None hosts = config.get('hosts', None) if hosts: players = [] for host in hosts.split(","): host = socket.gethostbyname(host) players.append(soco.SoCo(host)) if not players: players = soco.discover( interface_addr=config.get('interface_addr', None)) if not players: _LOGGER.warning('No Sonos speakers found.') return False add_devices(SonosDevice(hass, p) for p in players) _LOGGER.info('Added %s Sonos speakers', len(players)) return True
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Sonos platform.""" import soco if discovery_info: player = soco.SoCo(discovery_info) if player.is_visible: add_devices([SonosDevice(hass, player)]) return True return False players = None hosts = config.get('hosts', None) if hosts: # Support retro compatibility with comma separated list of hosts # from config hosts = hosts.split(',') if isinstance(hosts, str) else hosts players = [] for host in hosts: players.append(soco.SoCo(socket.gethostbyname(host))) if not players: players = soco.discover(interface_addr=config.get('interface_addr', None)) if not players: _LOGGER.warning('No Sonos speakers found.') return False add_devices(SonosDevice(hass, p) for p in players) _LOGGER.info('Added %s Sonos speakers', len(players)) return True
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Sonos platform.""" import soco if discovery_info: player = soco.SoCo(discovery_info) if player.is_visible: add_devices([SonosDevice(hass, player)]) return True return False players = None hosts = config.get('hosts', None) if hosts: # Support retro compatibility with comma separated list of hosts # from config hosts = hosts.split(',') if isinstance(hosts, str) else hosts players = [] for host in hosts: players.append(soco.SoCo(socket.gethostbyname(host))) if not players: players = soco.discover( interface_addr=config.get('interface_addr', None)) if not players: _LOGGER.warning('No Sonos speakers found.') return False devices = [SonosDevice(hass, p) for p in players] add_devices(devices) _LOGGER.info('Added %s Sonos speakers', len(players)) def group_players_service(service): """Group media players, use player as coordinator.""" entity_id = service.data.get('entity_id') if entity_id: _devices = [ device for device in devices if device.entity_id == entity_id ] else: _devices = devices for device in _devices: device.group_players() device.update_ha_state(True) descriptions = load_yaml_config_file( path.join(path.dirname(__file__), 'services.yaml')) hass.services.register(DOMAIN, SERVICE_GROUP_PLAYERS, group_players_service, descriptions.get(SERVICE_GROUP_PLAYERS)) return True
def kitchen(switch): if switch == "on": soco.SoCo("192.168.1.134").balance = (0, 100) soco.SoCo("192.168.1.134").play() print("family room should be playing music now...") return True elif switch == "off": soco.SoCo("192.168.1.134").stop() print("family room turned off...") return True else: print("Error in option choice") return False
def master_bedroom(): if switch == "on": soco.SoCo("192.168.1.127").balance = (100, 0) soco.SoCo("192.168.1.127").play() print("guest room should be playing music now...") return True elif switch == "off": soco.SoCo("192.168.1.127").stop() print("guest room turned off...") return True else: print("Error in option choice") return False
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Sonos platform.""" import soco global DEVICES advertise_addr = config.get(CONF_ADVERTISE_ADDR, None) if advertise_addr: soco.config.EVENT_ADVERTISE_IP = advertise_addr if discovery_info: player = soco.SoCo(discovery_info) # if device allready exists by config if player.uid in [x.unique_id for x in DEVICES]: return True if player.is_visible: device = SonosDevice(hass, player) add_devices([device], True) if not DEVICES: register_services(hass) DEVICES.append(device) return True return False players = None hosts = config.get(CONF_HOSTS, None) if hosts: # Support retro compatibility with comma separated list of hosts # from config hosts = hosts[0] if len(hosts) == 1 else hosts hosts = hosts.split(',') if isinstance(hosts, str) else hosts players = [] for host in hosts: players.append(soco.SoCo(socket.gethostbyname(host))) if not players: players = soco.discover(interface_addr=config.get(CONF_INTERFACE_ADDR)) if not players: _LOGGER.warning('No Sonos speakers found.') return False DEVICES = [SonosDevice(hass, p) for p in players] add_devices(DEVICES, True) register_services(hass) _LOGGER.info('Added %s Sonos speakers', len(players)) return True
def get_volume(self, speaker: Speaker) -> int: """Gets volume of passed Sonos speaker :param models.speaker.Speaker speaker: Speaker for which the volume gets requested """ soco_instance = soco.SoCo(speaker.ip_address) return soco_instance.volume
def soco(): """ Set up and tear down the soco fixture used by all tests. """ # Get the ip address from the command line, and create the soco object # Only one is used per test session, hence the decorator ip = pytest.config.option.IP if ip is None: pytest.fail("No ip address specified. Use the --ip option.") soco = soco_module.SoCo(ip) # Check the device is playing and has items in the queue if len(soco.get_queue()) == 0: pytest.fail('Integration tests on the SoCo class must be run ' 'with at least 1 item in the playlist.') transport_info = soco.get_current_transport_info() if transport_info['current_transport_state'] != 'PLAYING': pytest.fail('Integration tests on the SoCo class must be run ' 'with the Sonos unit playing.') # Save the device's state state = {'queue': soco.get_queue(0, 1000), 'current_track_info': soco.get_current_track_info()} # Yield the device to the test function yield soco # Tear down. Restore state soco.stop() soco.clear_queue() for track in state['queue']: soco.add_to_queue(track['uri']) soco.play_from_queue( int(state['current_track_info']['playlist_position']) - 1) soco.seek(state['current_track_info']['position']) soco.play()
def main(): """ Run the main script """ parser = argparse.ArgumentParser( prog='', description='Dump data about Sonos services' ) parser.add_argument( '-d', '--device', default=None, help="The ip address of the device to query. " "If none is supplied, a random device will be used" ) parser.add_argument( '-s', '--service', default=None, help="Dump data relating to services matching this regexp " "only, e.g. %(prog)s -s GroupRenderingControl" ) args = parser.parse_args() # get a zone player - any one will do if args.device: device = soco.SoCo(args.device) else: device = soco.discovery.any_soco() print("Querying %s" % device.player_name) # loop over each of the available services # pylint: disable=no-member services = (srv(device) for srv in soco.services.Service.__subclasses__()) for srv in services: if args.service is None or re.search( args.service, srv.service_type): print_details(srv)
def soco(request): """Set up and tear down the soco fixture used by all tests.""" # Get the ip address from the command line, and create the soco object # Only one is used per test session, hence the decorator ip = request.config.option.IP if ip is None: pytest.fail("No ip address specified. Use the --ip option.") soco_instance = soco_module.SoCo(ip) # Check the device is playing and has items in the queue if len(soco_instance.get_queue()) == 0: pytest.fail("Integration tests on the SoCo class must be run " "with at least 1 item in the playlist.") transport_info = soco_instance.get_current_transport_info() if transport_info["current_transport_state"] != "PLAYING": pytest.fail("Integration tests on the SoCo class must be run " "with the Sonos unit playing.") # Save the device's state state = { "queue": soco_instance.get_queue(0, 1000), "current_track_info": soco_instance.get_current_track_info(), } # Yield the device to the test function yield soco_instance # Tear down. Restore state soco_instance.stop() soco_instance.clear_queue() for track in state["queue"]: soco_instance.add_to_queue(track) soco_instance.play_from_queue( int(state["current_track_info"]["playlist_position"]) - 1) soco_instance.seek(state["current_track_info"]["position"]) soco_instance.play()
def power(self): speaker_data = {} if (self.ip != None): speakers = soco.discover() speaker_exists = False for speaker in speakers: if(self.ip == speaker.ip_address): speaker_exists = True if(speaker_exists == True): speaker = soco.SoCo(self.ip) else: speaker_data = { 'status' : 503, 'msg' : 'Sonos speaker are unavailable.' } else: speaker_data = { 'status' : 404, 'msg' : 'You need to defined the ip to the speaker you will connect to.' } return speaker_data
def get_speaker(name, local=False): # Use an IP address # (Allow the use of an IP address even if 'local' is specified) if Speakers.is_ipv4_address(name): logging.info("Using IP address instead of speaker name") return soco.SoCo(name) # Use the local speaker list if local: logging.info("Using local speaker list") return speaker_list.find(name) # Use discovery # Try various lookup methods in order of expense, # and cache results where possible speaker = None if not speaker: logging.info("Trying direct cache lookup") speaker = SPKR_CACHE.find(name) if not speaker: logging.info("Trying indirect cache lookup") speaker = SPKR_CACHE.find_indirect(name) if not speaker: logging.info("Trying standard discovery with network scan fallback") SPKR_CACHE.discover() speaker = SPKR_CACHE.find(name) if not speaker: logging.info("Trying network scan discovery") SPKR_CACHE.scan() speaker = SPKR_CACHE.find(name) if speaker: logging.info("Successful speaker discovery") else: logging.info("Failed to discover speaker") return speaker
def monitor(self): soco.config.EVENT_LISTENER_PORT = self.cfg['sonos']['event_port'] self.sonos = soco.SoCo( self.cfg['sonos']['ip']) self.yamaha = rxv.RXV( self.cfg['yamaha']['ctrl_url'], self.cfg['yamaha']['model_name']) self.log.info("{} ({}) Power={}, Input={}, Volume={}".format( self.cfg['yamaha']['friendly_name'], self.cfg['yamaha']['model_name'], self.yamaha.on, self.yamaha.input, self.yamaha.volume)) signal(SIGTERM, self.handle_sigterm) while self.break_loop is False: self._subscription() try: self.event = self.subscription.events.get(timeout=10) self.status = self.event.variables.get('transport_state') self._status() except Queue.Empty: pass except KeyboardInterrupt: self.handle_sigterm() break if self.break_loop: self.subscription.unsubscribe() soco.events.event_listener.stop()
def test_ring_sonos(component_ip, hub_ip): # pragma: no cover test_speaker = soco.SoCo(component_ip) if hub_ip is None: logger.error("Unable to extract Hub IP Address.") return False # The lighttpd server is configured to listen on port 81 # Resource files are stored in /www/pages/resources .. (on the hub) port = 81 uri_test = "http://" + hub_ip + ":" + str( port) + "/resources/swblaster.mp3" try: test_speaker.volume = 10 test_speaker.play_uri(uri_test) test_speaker.get_current_track_info() time.sleep(2) test_speaker.stop() try: test_speaker.play_from_queue(0) test_speaker.stop() except soco.SoCoException: # No action required, as the queue is empty. pass return True except (soco.SoCoException, HTTPNotFound) as e: logger.error("Error while testing Sonos: " + str(e)) return False
def get_all_speakers(self): soco_speakers = [] for speaker in self._speakers: soco_speakers.append(soco.SoCo(speaker.ip_address)) if soco_speakers: return soco_speakers return None
def __init__(self, name=None, sonos_ip=None, port=6060): self.machine_ip = self.detectIPAddress() self.port = port if name is None and sonos_ip is None: raise Exception("either name or sonos_ip must be provided") else: if name: device = soco.discovery.by_name(name) elif sonos_ip: device = soco.SoCo(sonos_ip) elif name and sonos_ip: device = soco.SoCo(sonos_ip) if device.player_name != name: raise Exception("name does not match sonos_ip") self.device = device
def pair_socos(l_ip, r_ip): l_soco = soco.SoCo(l_ip) r_soco = soco.SoCo(r_ip) l_uid = l_soco.uid r_uid = r_soco.uid req_addr = request_address_format.format(l_ip) req_headers = { "Content-Type": "application/xml", "SOAPAction": pair_soap_action, } req_payload = pair_payload_format.format(l_uid, r_uid) response = requests.post(req_addr, data=req_payload, headers=req_headers) if response.status_code != 200: print("failed to pair")
def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Sonos platform.""" import soco global DEVICES if discovery_info: player = soco.SoCo(discovery_info) # if device allready exists by config if player.uid in DEVICES: return True if player.is_visible: device = SonosDevice(hass, player) add_devices([device]) if not DEVICES: register_services(hass) DEVICES.append(device) return True return False players = None hosts = config.get('hosts', None) if hosts: # Support retro compatibility with comma separated list of hosts # from config hosts = hosts.split(',') if isinstance(hosts, str) else hosts players = [] for host in hosts: players.append(soco.SoCo(socket.gethostbyname(host))) if not players: players = soco.discover(interface_addr=config.get('interface_addr', None)) if not players: _LOGGER.warning('No Sonos speakers found.') return False DEVICES = [SonosDevice(hass, p) for p in players] add_devices(DEVICES) register_services(hass) _LOGGER.info('Added %s Sonos speakers', len(players)) return True
def get_speaker(name, local=False): # Allow the use of an IP address even if 'local' is specified if Speakers.is_ipv4_address(name): logging.info("Using IP address instead of speaker name") return soco.SoCo(name) if local: logging.info("Using local speaker list") return speaker_list.find(name) else: logging.info("Using SoCo speaker discovery") return soco.discovery.by_name(name)
def precedente(hermes, intentMessage): conf = read_configuration_file(CONFIG_INI) current_session_id = intentMessage.session_id addr_ = conf['global']['ip'] port_ = conf['global']['port'] user_ = conf['global']['user'] password_ = conf['global']['password'] zone = soco.SoCo('192.168.10.4') zone.previous() hermes.publish_end_session(current_session_id, "OK")
def ramp_to_volume(self, speaker: Speaker, volume: int): """Ramps volume to target volume for the passed Sonos speaker :param models.speaker.Speaker speaker: Speaker to control :param int volume: Volume to ramp up or down to """ soco_instance = soco.SoCo(speaker.ip_address) soco_slaves = list(self.get_stereo_pair_slaves(speaker)) soco_slaves_volumes = [x.volume for x in soco_slaves] soco_instance.ramp_to_volume(volume) for index, slave in enumerate(soco_slaves): slave.volume = soco_slaves_volumes[index]
def set_volume(self, speaker: Speaker, volume: int): """Sets volume for passed Sonos speaker :param models.speaker.Speaker speaker: Speaker to control :param int volume: Volume to set """ soco_instance = soco.SoCo(speaker.ip_address) soco_slaves = list(self.get_stereo_pair_slaves(speaker)) soco_slaves_volumes = [x.volume for x in soco_slaves] soco_instance.volume = volume for index, slave in enumerate(soco_slaves): slave.volume = soco_slaves_volumes[index]
def get_coordinator_instance(self, speaker: Speaker) -> soco.SoCo: """Get the SoCo instance of the passed speaker or, if the passed speaker is in a group, get the groups coordinators SoCo instance. :param models.speaker.Speaker speaker: Speaker whos instance / coordinators instance should be returned :returns: SoCo instance or coordinators SoCo instance :rtype: soco.Soco """ soco_instance = soco.SoCo(speaker.ip_address) if soco_instance.group is not None and soco_instance.group.coordinator is not None: soco_instance = soco_instance.group.coordinator return soco_instance
def define_player(ip_address, name): """Returning a SoCo object of the chosen player""" player = None if ip_address: player = soco.SoCo(ip_address) if name: player = get_player_by_name(name) if player and GROUP: # Change player to be the coordinator of the group player = player.group.coordinator return player
def set_master(speaker): try: ip_address(speaker) except ValueError: pass else: return soco.SoCo(speaker) sps = get_sonos_players() if not sps: return None sp_names = {s.player_name:s for s in sps} return sp_names.get(speaker)
def init(**kwargs): """ Initialize variables for the unittests that are only known at run time """ global SOCO # pylint: disable-msg=W0603 SOCO = soco.SoCo(kwargs['ip']) if len(SOCO.get_queue()) == 0: raise SoCoUnitTestInitError('Unit tests on the SoCo class must be run ' 'with at least 1 item in the playlist') transport_info = SOCO.get_current_transport_info() if transport_info['current_transport_state'] != 'PLAYING': raise SoCoUnitTestInitError('Unit tests on the SoCo class must be run ' 'with the sonos unit playing')
def _stream_to_speaker(self, speaker_ip, episodes): """ Play or enqueue selected episodes """ urls = [episode.url for episode in episodes if SONOS_CAN_PLAY(episode)] logger.info('Streaming to Sonos %s: %s'%(speaker_ip, ', '.join(urls))) controller = soco.SoCo(speaker_ip) # enqueue and play for episode in episodes: controller.add_to_queue(episode.url) episode.playback_mark() controller.play()
def run(self): if not self.player: if self.ip: self.player = soco.SoCo(self.ip) elif self.name: self.player = soco.discovery.by_name(self.name) else: self.player = soco.discovery.any_soco() if not self.player: self.output = self.output_no_connection return try: track_info = self.group_coordinator.get_current_track_info() transp_info = self.group_coordinator.get_current_transport_info() player_name = self.player.player_name muted = self.player.mute volume = self.player.volume except: self.output = self.output_no_connection return state = transp_info["current_transport_state"] cdict = { "player_name": player_name, "volume": volume, "muted": "M" if muted else "", "title": track_info["title"], "artist": track_info["artist"], "album": track_info["album"], "duration": track_info["duration"][2:], "position": track_info["position"][2:], "state": self.state_text_map[state], } self.data = cdict if self.format_no_music is not None and state == "STOPPED": self.output = { "full_text": self.format_no_music.format(**cdict), "color": self.color_no_music } else: self.output = { "full_text": self.format.format(**cdict), "color": self.color }