Listening to music on vinyl is great. It's physical and tactile. You listen to a whole album rather than random tracks. You notice when it's over and consciously choose something else. You can build a collection and browse through it rather than having to search for exactly what you want.
It's also expensive and bulky, especially when you consider that any money you spend on vinyl is very likely a duplicate of music that you already have access to through a streaming service you subscribe to.
This project attempts to replicate the tactility and collection-building aspects of vinyl while relying on Spotify to actually deliver the music. Placing a physical object on an NFC reader hooked up to a Raspberry Pi (both of which can be hidden away) will start playing the album associated with that tag.
I will walk you through all the steps - from setting up the Raspberry Pi to encoding the NFC tags. This is my very first Raspberry Pi project and my first Python code, so I taught myself both while developing this. As such, these instructions assume literally zero previous knowledge and talk you through every step.
If you are familiar with how to set up a Raspberry Pi or already have one set up then you can skip quite a few of the early steps and
start here
.The total cost for the essential components to build this is approximately £50-60 depending on how much you spend on the NFC reader.
The code is maintained at github: https://github.com/hankhank10/vinylemulator
If you run into difficulties on this the best way to get help is to raise a github issue here (https://github.com/hankhank10/vinylemulator/issues). You can also try posting in the comments below but I am trying to consolidate issues through github wherever possible as it's a more structured way of responding.
I'd love to see what you build!
Important note:Since developing this code in early 2020 it's become apparent that a number of the newer ACR122U NFC readers (which is what I recommend for this project) are not compatible with NFCpy, which is the library that my Python code uses.
Even worse, there seems to be no way to know whether the ACR122U reader you are going to get will work or not... which is annoying.
Luckily ryanolf has created a new library which is compatible with the newer readers and is available here: https://github.com/ryanolf/node-sonos-nfc
Step 1: Set up your Raspberry PiIf you have a setup and running Raspberry Pi then skip to Step 2.
If you don't, then go through my super-simple, no-prior-knowledge-assumed, every-single-step-explained tutorial on how to set one up here. It takes max one hour and assumes zero prior knowledge (promise). See you back here when you're done.
Ok, on to Step 2.
Step 2: Install Node.js and NPMConnect to your Raspberry Pi command line either through SSH (Terminal / Putty) or VNC.
(Top tip: You can copy text from your Mac/PC and paste it to the Raspberry Pi via VNC by pressing CONTROL-V, but if you're trying to paste into the Terminal within VNC then you need to press CONTROL-SHIFT-V)
We are now going to install the dependencies we need.
First job is to check again your software is up to date by typing the following two commands. They might take a while to download and install.
sudo apt update
sudo apt upgrade
Next you want to download and install node.js and NPM (don't worry too much about what they are, they are helpful and necessary for our next tasks) by typing the following:
sudo apt-get install nodejs npm
It will ask you a couple of times if you're happy to take up disk space with these - you are so press Y
Step 3: Install the SONOS HTTP APIThe basis of the back end for our project is the node-sonos-http-api package created by jishi. You can read all about it here: https://github.com/jishi/node-sonos-http-api
Let's first check that we have "git" installed:
apt install git
Then download the code with the following command entered into the command line on your Raspberry Pi:
git clone https://github.com/jishi/node-sonos-http-api.git
and we will install it with the following commands
cd node-sonos-http-api
npm install --production
We can then run it with the following command:
npm start
Once that's done we should test that it is working.
First of all, open the internet browser on our Raspberry Pi and navigate to http://localhost:5005/. A nice interface should open with the Sonos logo and some documentation on how the API works.
Next, let's check that this is working from the wider network by using a browser on another PC or Mac on the same network and navigating to http://[theIPaddressofyourPi]:5005/ and seeing if we get the same result. We should.
Now we will actually make the system do something. Use a browser and navigate to:
http://192.168.4.102:5005/Dining Room/playpause
You should replace the above IP address with the address of your Raspberry Pi and "Dining Room" with one of the names of your Sonos zones. It should either play or pause (depending on whether music is already playing or not) the music in that room. Obviously something needs to be in the Sonos queue for that to work.
Going forward, I'm going to use the above IP address and Dining Room as the examples throughout this tutorial. Obviously you should replace them with your IP address and your zone name on each occasion.
Step 4: Make the Sonos HTTP API Run ConstantlyIt's great that we've got the Sonos HTTP API running, but what if it crashes? Or you lose power or need to reboot your Raspberry Pi?
You can see the effect by closing down the terminal window and retrying what we just tried. It won't work because the HTTP API has stopped along with the terminal window.
We actually want this to run constantly and do so from startup each time. We do this with a cool thing called PM2.
In a fresh terminal window, install and run it as follows:
sudo npm install -g pm2
pm2 status
Now let's get it to run our Sonos HTTP API:
cd node-sonos-http-api
pm2 start npm -- start
pm2 startup systemd
This last command generate something which looks a bit like:
sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u pi --hp /home/pi
Copy what your Pi generates (not the exact text above - yours may be different) and enter it into the command line. This instructs the system to run PM2 on boot every time.
Finally, enter:
pm2 save
which saves everything down.
Now test whether this has worked by rebooting your Raspberry Pi with the command
sudo reboot
Hopefully once the Pi reboots it will also start PM2 and in turn the Sonos HTTP API. You can check this by navigating using a browser on the same network to the address we used before and see the Sonos logo and instructions:
http://192.168.4.102:5005/
(yours will depend on the IP address)
Step 5: Play Some SpotifyLet's check that the service can access Spotify.
Open a browser and navigate to the following address (obviously replacing with your IP address and room name):
192.168.4.102:5005/Dining Room/spotify/now/spotify:album:2dfTV7CktUEBkZCHiB7VQB
You should hear some John Grant. Enjoy.
Step 6: Find Spotify URIsWeird, I know, but not everybody likes John Grant. Maybe you want to listen to something else?
You can get the Spotify links from the desktop, web or mobile apps but the Desktop is by far the easiest as it delivers the URI in exactly the format you want so start with that.
In the Spotify desktop app navigate to the album you want to listen to (maybe Lemonade by Beyonce?)
Click on the three little dots next to the heart button.
Go down the menu to Share and choose Copy Spotify URI
This will copy something like
spotify:album:7dK54iZuOxXFarGhXwEXfF
to your clipboard, which is the Spotify URI for Beyonce's Lemondade album.
Fire up your browser again and navigate to the following address (obviously replacing the IP address and room and pasting in the URI you just copied):
192.168.4.102:5005/Dining Room/spotify/now/[Spotify URI you want to play]
You should hear your choice play.
If you prefer to use the web app then it will give you a web link (something like the below):
https://open.spotify.com/album/7dK54iZuOxXFarGhXwEXfF
you need to convert this to the spotify:album:code format above for it to work.
Step 7: A Note on Spotify URIsSpotify URIs and they way they interface with the node-sonos-http-api are intuitive, for the most part.
You can link directly to albums, tracks and playlists.
An album URI looks like:
spotify:album:6agCM9GJcebduMddgFmgsO
A track URI looks like:
spotify:track:4fNDKbaeEjk2P4GrRE1UbW
Playlists work a little differently. When you copy the URI from Spotify it will look something like:
spotify:playlist:5huIma0YU4iusLcT2reVEU
However, to actually get it to work on the API you need to add spotify:user: to the beginning of the above. This applies even to public playlists and, yes, it means that you are saying spotify twice.
To be very clear, user doesn't need to be a particular user's name, just the text user. So the correct URI for the above playlist to get it to work would be:
spotify:user:spotify:playlist:5huIma0YU4iusLcT2reVEU
Step 8: Set Up Raspberry Pi to Send HTTP RequestsRather than manually typing HTTP requests into a web browser, we want to automate it so that the Raspberry Pi does that itself when presented with certain stimulus (the NFC reader being triggered).
We will be using a library called requests to allow our Raspberry Pi to do this. Let's check it's installed.
Open up the terminal on your Pi and type the following:
sudo pip install requests
It's likely that it comes back and says it's installed already, in which case great. If not, it will install it.
Step 9: Generate NFCC Tag(s) With Spotify DataNow we want to write a Spotify album URI to a NFC tag. Each of these tags are what you will use to tell the Raspberry Pi to play a particular album.
You can write to an NFC tag using an Android phone, but I find it easiest to do so via a mac or PC as then you can get the is easiest to get the Spotify URIs from the Spotify desktop app.
Plug your USB NFC reader into your PC or Mac. I am using the ACR122U by American Card Systems.
Download NFC Tools to your PC or Mac. Install and open it up.
It can be a little slow to connect to the reader sometimes and may say that it can't find the reader at all. Go to the Other tab in NFC tools and click every so often on the Connected NFC Reader button. You may have to unplug and replug the reader a few times before it finds it.
Eventually it will give you the option to choose your reader from a list and say that it is connected. Go to the Information tab which will show nothing except "Waiting for an NFC tag".
Take a blank NFC tag. Put it on the reader and leave it there. NFC Tools will display the information about the tag.
Go to the Write tab and click Add a record > Text. (Be careful not to choose URL or URI - I know it's tempting because you're copying a URI, but you want text)
Grab a URI from Spotify using the method we used previously. If you want an easy example then the following is our John Grant album from earlier.
spotify:album:2dfTV7CktUEBkZCHiB7VQB
Click OK and then click Write (don't forget this last step - it doesn't actually write it until you click this). It will tell you it's written the tag successfully.
Take the tag off the reader
Step 10: Set Up the NFC Reader on the Raspberry PiPlug your NFC reader into one of the USB ports on your Raspberry Pi.
We will use the nfcpy Python library to communicate with the NFC reader. Install it by typing the following on your Pi command line:
pip install -U nfcpy
We can then check whether this library is able to see our NFC reader by typing the following:
python -m nfc
If it has worked then you will see the following:
This is the 1.0.3 version of nfcpy run in Python 2.7.16 on Linux-4.19.97-v7+-armv7l-with-debian-10.3
I'm now searching your system for contactless devices
** found ACS ACR122U PN532v1.6 at usb:001:011
I'm not trying serial devices because you haven't told me
-- add the option '--search-tty' to have me looking
-- but beware that this may break other serial devs
However there's a good chance that you get an error message saying that the reader has been found but your user (pi)does not have permission to access it. If you do get this error message then it will also explain how to fix the problem, which is by typing two commands which looks a bit like the following:
sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"04e6\", ATTRS{idProduct}==\"5591\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'
sudo udevadm control -R
Copy and execute both of the commands it gives you (not exactly what is above, since yours may be different), then unplug and replug your NFC reader from the USB port.
Try the check command again:
python -m nfc
This time it should say that it's found it without error messages.
Step 11: Install the vinylemulator python scriptsWe now have all the building blocks in place:
- Our Raspberry Pi is able to listen for NFC input
- Our Raspberry Pi is able to tell Sonos to play Spotify playlists when given a Spotify URI
- We have an NFC tag with a Spotify URI stored on it
Now we need to pull all these building blocks into something useful. This is done through a short python script I wrote (with a lot of help from previous NFC/Spotify/Sonos projects) which is called vinylemulator.
You can view the source code for the files at github: https://github.com/hankhank10/vinylemulator
To install this onto our Raspberry Pi we need to clone it from github with the following command:
git clone https://github.com/hankhank10/vinylemulator.git
Step 12: Customise vinylemulatorOpen the Raspberry Pi file manager and navigate to home > pi > vinylemulator
Open the file usersettings.py
One of the lines in this file will read:
sonosroom="Dining Room"
Change "Dining Room" to be whichever Sonos room name you want to control.
There is also a setting in this file which allows you to customise the IP address of the sonos-http-api. You should be able to leave this unchanged as "localhost" which just means it will use the Raspberry Pi it is running on.
Save the file and close it.
Step 13: Test vinylemulatorGo to your Raspberry Pi command prompt.
Enter the following command:
python vinylemulator/readnfc.py
If all is well this will load up the script and say that the reader is ready. The light on the reader should go green.
Put the NFC tag on the reader, which will beep.
The terminal will show what it has read from the NFC tag and show the HTTP request address that it has sent. Your album of choice should play from your Sonos speakers.
This script will keep running until you close the terminal window. You can tap different album NFC tags and it will switch to that album.
Step 14: Get vinylemulator to run constantly and on startupJust like the sonos-http-api, we want vinylemulator to run all the time rather than just when we call it. We can use pm2 to do this again.
First close down any instances of vinylemulator you are running by closing their terminal windows.
Then open up a fresh terminal window and type the following two commands:
pm2 start vinylemulator/readnfc.py
pm2 save
Let's check if that has worked by rebooting the Raspberry Pi. (You can either type sudo reboot or do so from the Raspberry menu with your mouse.
Wait for the Pi to start up again and see it it works by tapping an NFC tag on the reader. You should get music.
Step 15: Congratulate YourselfEverything is now functional. You can move the Raspberry Pi to wherever you plan to site it. It will restart and operate in the way you've set it up any time you plug it in.
Your next tasks are the fun ones: making it all beautiful.
THANK YOU!Thank you so much for the incredible response to this and my other projects! I'm so excited that so many of you are building these cool little toys.
I've had a lot of questions about whether I will be building and selling these. The answer is definitely not: this is a hobby for me and part of the fun is the elbow grease that goes in.
I think I've made the instructions possible for everyone, but if you do run into difficulties on this the best way to get help is to raise a github issue here (https://github.com/hankhank10/vinylemulator/issues). You can also try posting in the comments below but I am trying to consolidate issues through github wherever possible as it's a more structured way of responding.
I don't accept donations but if you are inspired by my projects and want to recognise the work then you can buy me a coffee here.
Extra credit: Make It Beautiful - Hide Your ReaderThe first part of making it beautiful is hiding the nasty white plastic NFC reader away somewhere.
My favourite implementation is to take an old Sonos Bridge (which are now redundant, and can be bought for £3 on eBay), stripping out the innards and putting the NFC reader inside there.
The lowest tech option I tried is taping the reader to the underside of a counter next to my Sonos Play:5. The wood of the counter is thin enough that the NFC can go through, so I play music by tapping a NFC tag on a magical and invisible spot.
Next you will want to get some album art printed. You can do this yourself, but I got them printed as photos onto 350 gsm card stock.
In the UK Super Snaps do 100 square prints with a nice black border onto card for £26 which I found difficult to beat.
Comments