Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- Handles connecting to a chromecast device and playing music on the device via Spotify
- '''
- import argparse
- import logging
- import sys
- import time
- import nfc
- import pychromecast
- from pychromecast.controllers.spotify import SpotifyController
- import spotify_token as st
- import spotipy
- from spotipy.oauth2 import SpotifyOAuth
- import constants
- CAST_NAME = constants.CAST_NAME
- CAST_IP = constants.CAST_IP
- SP_DC = constants.SP_DC
- SP_KEY = constants.SP_KEY
- CLIENT_ID = constants.CLIENT_ID
- CLIENT_SECRET = constants.CLIENT_SECRET
- SPOTIPY_REDIRECT_URI = constants.REDIRECT_URI
- SPOTIFY_USERNAME = constants.USERNAME
- ALLOW_EXPLICIT = constants.ALLOW_EXPLICIT
- SHUFFLE_DEFAULT = constants.SHUFFLE_DEFAULT
- PLAYLISTS_SHUFFLE = constants.PLAYLIST_SHUFFLE
- parser = argparse.ArgumentParser(description="Cast songs/albums to Google Home via nfc controls.")
- parser.add_argument("--show-debug", help="Enable debug log", action="store_true")
- parser.add_argument("--cast", help='Name of cast device (default: "%(default)s")', default=CAST_NAME)
- args = parser.parse_args()
- if args.show_debug:
- logging.basicConfig(level=logging.DEBUG)
- print('Version: ' + constants.VERSION)
- def n():
- '''
- prints a new line
- '''
- print("\n")
- def isSameSongPlaying(dictionary, tag_uri):
- '''
- returns True if the same song is playing and False if it is not.
- params:
- dictionary: dictionary returned from "client.current_playback('US')"
- tag_uri: the URI of the song being comapared to the currently playing song
- '''
- if dictionary == None: #If no song is playing
- return False
- context_dictionary = dictionary.get('context')
- if context_dictionary == None:
- return False
- current_uri = context_dictionary.get('uri')
- if current_uri == None:
- return False
- if current_uri == tag_uri: #If the song is playing
- return True
- else: #If a different song is playing
- return False
- def find(string, search_term):
- '''
- returns True if 'search_term' is found anywhere in 'string'
- '''
- if string.find(search_term) != -1:
- return True
- else:
- return False
- chromecasts, browser = pychromecast.get_listed_chromecasts(friendly_names=[args.cast])
- home = None
- for _cast in chromecasts:
- if _cast.name == args.cast:
- home = _cast
- break
- if not home:
- print('No chromecast with name "{}" discovered'.format(args.cast))
- print("Discovered casts: {}".format(chromecasts))
- print("Attempting to connect to cast devie via IP")
- n()
- home = pychromecast.Chromecast(CAST_IP)
- if not home:
- print("Failure. Exiting.")
- sys.exit(1)
- else:
- print("Success!")
- n()
- print("cast {}".format(home))
- home.wait() # Start a new worker thread/wait for connection
- # Log device and status
- n()
- print(home.device)
- n()
- print(home.status)
- n()
- spotify_device_id = None
- # Create a spotify token
- data = st.start_session(SP_DC, SP_KEY)
- access_token = data[0]
- expires = data[1] - int(time.time())
- # Create a spotify client
- scope = "streaming user-read-playback-state user-modify-playback-state"
- client = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, scope=scope, redirect_uri=SPOTIPY_REDIRECT_URI, username=SPOTIFY_USERNAME))
- if args.show_debug:
- spotipy.trace = True
- spotipy.trace_out = True
- # Launch the spotify app on the home
- sp = SpotifyController(access_token, expires)
- home.register_handler(sp)
- sp.launch_app()
- n()
- print(home.status)
- n()
- if not sp.is_launched and not sp.credential_error:
- print("Failed to launch spotify controller due to timeout")
- sys.exit(1)
- if not sp.is_launched and sp.credential_error:
- print("Failed to launch spotify controller due to credential error")
- sys.exit(1)
- # Query spotify for active devices
- devices_available = client.devices()
- # Match active spotify devices with the spotify controller's device id
- for device in devices_available["devices"]:
- if device["id"] == sp.device:
- spotify_device_id = device["id"]
- break
- if not spotify_device_id:
- print('No device with id "{}" known by Spotify'.format(sp.device))
- print("Known devices: {}".format(devices_available["devices"]))
- sys.exit(1)
- #Set up NFC reader
- n()
- print("Setting up the NFC reader")
- reader = nfc.ContactlessFrontend(constants.PATH)
- print(reader)
- n()
- shuffle_state = SHUFFLE_DEFAULT
- explicit_filter = ALLOW_EXPLICIT
- def get_record(tag_data):
- shuffle_state = SHUFFLE_DEFAULT
- explicit_filter = ALLOW_EXPLICIT
- if tag_data.ndef:
- for record in tag_data.ndef.records:
- nfc_data = record.text
- print("Read from NFC tag: " + record.text)
- nfc_data = nfc_data.lower() #make it lowercase
- reset_shuffle = False
- command = nfc_data
- if type(command) == type('string-example'):
- if command.startswith('spotify'):
- playback_data = client.current_playback('US')
- tag_uri = command #These variables have the same exact value
- # Overide shuffle based on media type
- if find(command, 'playlist'):
- client.shuffle(PLAYLISTS_SHUFFLE, spotify_device_id)
- reset_shuffle = True
- elif find(command, 'show'):
- client.shuffle(False, spotify_device_id)
- reset_shuffle = True
- if not isSameSongPlaying(playback_data, tag_uri):
- client.start_playback(device_id=spotify_device_id, context_uri=tag_uri)
- time.sleep(0.1)
- # If we overid the shuffle state, change it back to normal
- if reset_shuffle:
- client.shuffle(shuffle_state, spotify_device_id)
- elif command == 'command:skip':
- client.next_track(spotify_device_id)
- elif command == 'command:previous':
- client.previous_track(spotify_device_id)
- elif command == 'command:pause':
- client.pause_playback(spotify_device_id)
- elif command == 'command:shuffle':
- shuffle_state = not shuffle_state
- client.shuffle(shuffle_state, spotify_device_id)
- elif command == 'command:explicit':
- explicit_filter = not explicit_filter
- else:
- n()
- print('Oopsies, that NFC tag has an invalid command.')
- time.sleep(0.1)
- else:
- n()
- print("The NFC reader could not read this tag.")
- n()
- print("This may be because:")
- print("- You are using a Mifare Classic NFC tag, which is not supported by your reader.")
- print("- The NFC tag you are trying to read is not storing URI's or commands at text.")
- # Start playback
- while True:
- reader.connect(rdwr={'on-connect': get_record, 'beep-on-connect': constants.BEEP})
- # Shut down discovery
- pychromecast.discovery.stop_discovery(browser)
Add Comment
Please, Sign In to add comment