Creating a Raspberry Pi Pandora Player with Remote Web Control

pi pandora
In our last article, we learned how to control a Raspberry Pi from a mobile device and, as a bonus, we created a menu to make it even easier to issue commands and control our Pi. We’re back today to put that remote menu to good use because we’re building an amazing Pandora music player we can connect to a stereo in our living room, for example, without a monitor, keyboard, or mouse. Our system will include a web interface served through Node.js so we can control our Pandora player remotely from a mobile phone—all from the comfort of our couch. 🙂 Follow along with me and let’s make this happen!

Article Contents

Complete Prerequisites

Prepare your Raspberry Pi

If you have not already followed my Beginner’s Guide to Installing Node.js on a Raspberry Pi, I recommend that you take a look at that now. In this guide, I equip you with the knowledge needed to build an awesome Raspberry Pi system that can also run in a headless mode. We’re able to avoid a dedicated monitor, keyboard, and mouse, and this is exactly what we need to maximize the awesomeness of our Pandora player.

At the very least, make sure you follow the steps to install Node.js because Node.js will be powering the built-in Pandora web server we’ll be accessing from our mobile devices.

Create Pandora account

If you do not already have a Pandora account, go ahead and visit and create one now. Pandora is “free personalized radio that plays the music you love”. What’s not to love about that? 🙂

While you are logged into Pandora, go ahead and create a couple of stations. Our remote web interface will ultimately need stations in order to to play music for us.

Install additional packages

We’ll need a couple of additional packages to utilize our Pandora player. First, let’s install pianobar, an amazing console-based player underpinning our entire project:

$ sudo apt install pianobar

Next, we’ll install screen, a terminal-based window manager that our software will use behind the scenes in conjunction with pianobar:

$ sudo apt install screen

Install Patiobar

As a next step, we’ll install and configure Patiobar, a web frontend for pianobar created by Kyle Johnson. I was gearing up to create a web interface to pianobar and came across Kyle’s project. He has done an excellent job, and we’ll be leveraging his work to create this fantastic music system.

Go ahead and ensure your terminal session is in your home directory:

$ cd ~

Also, these very next steps require Node.js so make sure you have that installed.

Ok, let’s install Patiobar.  Execute this next set of commands one by one from the terminal:

$ git clone
$ cd Patiobar
$ bash

Excellent! We just made some serious progress and installed the foundational elements needed for our Patiobar web server.

Configure pianobar so it’s ready to be used by Patiobar

Our Patiobar web frontend ultimately uses pianobar behind the scenes to serve up music from Pandora so we need to make sure pianobar is configured and in working order first.

Launch the pianobar configuration file for editing using the Leafpad text editor:

$ leafpad ~/.config/pianobar/config &

The contents will look something like this:

user =
user =
password = password
#autostart_station = 123456
audio_quality = high
event_command = /home/pi/Patiobar/
fifo = /home/pi/Patiobar/ctl
tls_fingerprint = FC2E6AF49FC63AEDAD1078DC22D1185B809E7534

Substitute the user parameter with your Pandora user account email, and substitute the password with your Pandora password, and save your changes.

Great work! We’re making excellent progress and we’re ready to launch pianobar by itself to confirm it works. Connect a set of earbuds or speakers to the audio output jack of your Raspberry Pi. Get ready to hear some music!

Issue the following command to launch pianobar:

$ pianobar

At this point, pianobar should log into Pandora and prompt you to select a station for listening. Go ahead and select the default station that you would like to start each time the Raspberry Pi music player starts. You will be able to change this station from the web interface that is provided, but we need a starting station to bootstrap our player each time it starts. The pianobar station selection dialog will look something like this:

[?] Select station: 2
|> Station "David Nevue (Holiday) Radio" (3749270268933429865)

After selecting a station, hit Ctrl+C to quit. You will need the long station number listed in parentheses, 3749270268933429865, as shown in our example above, for the next step.

Edit the pianobar configuration file one more time:

$ leafpad ~/.config/pianobar/config &

Replace the existing autostart_station line with the long station number you obtained above. Be sure to remove the “#” from the beginning of the line so pianobar can read the autostart_station configuration information.

autostart_station = 3749270268933429865

Save your changes and launch pianobar again.

$ pianobar

This time, pianobar should jump right in and begin playing your default station without intervention required by you. Assuming this is the case, you are ready to finish the installation so we can use pianobar with the awesome Patiobar web frontend powered by Node.js.

Create Patiobar start and stop scripts

Okay, let’s create a couple of scripts to make it easy to start and stop Patiobar.

Create bin directory to make our menu command accessible from any directory

First, we will create a directory so our scripts will be accessible from any directory on our system without the need to provide a full path name to our script.

From the terminal, return to your home directory if you are not already there.

$ cd ~

Next, create a directory called bin:

$ mkdir bin

We will need to edit our .bashrc file to include this bin directory in our PATH variable. This will ensure that any scripts located in our newly created bin directory can be invoked from any directory on our system without needing to include the full path to the script. Let’s first launch a text editor so we can edit the .bashrc file:

$ leafpad .bashrc &

Add the following line to the bottom of this file:

export PATH="$HOME/bin:$PATH"

Save your changes and close the leafpad editor.

To ensure our changes to the .bashrc file are processed right away, invoke this command:

$ source .bashrc

Perfect! We are now positioned to create our Patiobar start and stop scripts.

Create pbstart (Patiobar start) command

We’ll use leafpad once again to create our new command. We’ll call our command pbstart (Patiobar start):

$ leafpad ~/bin/pbstart &

Add the following contents and save the file.


cd /home/pi/Patiobar

# Kill any old Patiobar processes running
pbstop 1> /dev/null

screen -S pianobar -d -m bash -c 'pianobar'

# The "patiobar" in the end is not needed and is used as an identifier so we can kill it when stopping.
# Otherwise, we might kill other "node index.js" processes.
node index.js patiobar > /dev/null 2>&1 &

echo "Go to http://$(hostname):3000/ to launch the Web interface."

Create pbstop (Patiobar stop) command

Using leafpad once again, create a second command called pbstop (Patiobar stop):

$ leafpad ~/bin/pbstop &

Add the following contents and save the file.


echo Closing out Pandora processes...
pkill -xf "SCREEN -S pianobar -d -m bash -c pianobar"
pkill -xf "node index.js patiobar"
echo done

Set user execute bit on the pbstart/stop scripts

Finally, set the user execute bit on both files so the pi user has permission to run the scripts:

$ chmod u+x ~/bin/pbstart
$ chmod u+x ~/bin/pbstop

Launch Patiobar and start listening to music!

Okay, here’s the moment of truth. Let’s try out our pbstart command and see if we can start up Patiobar. Remember that we can invoke this command from any directory on our system since it is part of our PATH. Here we go!

$ pbstart

Patiobar should start up pianobar, and you should both hear music and be able to navigate to the Patiobar web interface running on port 3000. For example, my Raspberry Pi host name is called “pandora” so I would navigate to http://pandora:3000. It’s December and I’m listening to Christmas music so this is what I see when launching the web interface from my mobile phone:
David Nevue
The interface is excellent and we can change stations using the “hamburger” menu in the top right, and pause, skip songs, etc. There’s even album art as you can see!

When you are done listening, stop the Patiobar player so you do not consume all your Pandora minutes:

$ pbstop

Install SSH client on mobile phone to control Pianobar start/stop remotely (optional)

We learned how to control a Raspberry Pi from a mobile device] in our last article and I encourage you to read that article to learn how to install an SSH client on your mobile device so you can invoke terminal commands from your phone. It’s pretty amazing and useful to not be tethered to a laptop or desktop and still log in and interact with your Pi!

After the mobile SSH client is installed you will be able to invoke pbstart from your mobile device to start Patiobar, stop Pianobar with pbstop, and safety shut down your Pi using the following command:

$ sudo poweroff

Utilizing a mobile SSH client is a much better option for shutting down your headless Pi gracefully rather than yanking the power cord out and risking potential corruption of your microSD card.

Add menu for remote control from mobile phone (optional)

To make it even easier to invoke commands, our last article on controlling a Raspberry Pi from a mobile device also included a bonus section on creating a menu system. You can follow the steps in that article to create a menu system that looks something like this for our current Pandora player project:
rmenu pandora
After following the steps in the controlling a Raspberry Pi from a mobile device article, you can create a file called in the same directory as the rmenu command like this:

$ leafpad ~/bin/ &

…and add the following contents:

show_menu () {
    # We show the host name right in the menu title so we know which Pi we are connected to
    OPTION=$(whiptail --title "Menu (Host:$(hostname))" --menu "Choose your option:" 12 36 5 \
    "1" "Uptime" \
    "2" "Start Pandora" \
    "3" "Stop Pandora" \
    "4" "Reboot Pi" \
    "5" "Shut down Pi"  3>&1 1>&2 2>&3)

    # Check if user pressed cancel or escape
    if [[ ($BUTTON -eq 1) || ($BUTTON -eq 255) ]]; then
        exit 1

    if [ $BUTTON -eq 0 ]; then
        case $OPTION in
            whiptail --title "Uptime info" --msgbox "$MSG" 8 36
            msg="Go to http://$(hostname):3000/ to launch the Web interface."
            whiptail --title "Note" --msgbox "$msg" 8 36
            sleep 2
            confirmAnswer "Are you sure you want to reboot the Pi?"
            if [ $? = 0 ]; then
                echo Rebooting...
                sudo reboot
            confirmAnswer "Are you sure you want to shut down the Pi?"
            if [ $? = 0 ]; then
                echo Shutting down...
                sudo poweroff

This new menu ( can then be invoked from rmenu as follows:

$ rmenu -m 2

As a final step (as outlined in the previous article), you can add this rmenu -m 2 command to ~/.profile so the menu starts automatically when you SSH into the Pi from your mobile device.

Launch Patiobar automatically on startup (optional)

If you have a dedicated microSD card for your Pandora player, you might want to start Patiobar automatically each time you power on your Raspberry Pi. This makes it easier to, for example, power on a Pi connected to speakers in your living room without the need to SSH into the Pi upon boot to issue a pbstart command. The downside is that you might be playing music and burning Pandora time when you don’t even realize music is playing. 🙂

To start Patiobar automatically every time you boot, use sudo to edit the following file since this file requires root privileges:

$ sudo leafpad /etc/rc.local &

Add the following line just above the last line in the file with the contents of exit 0:

sleep 15 && sudo -iu pi /home/pi/bin/pbstart

The /etc/rc.local script runs every time the Pi boots up. We sleep for 15 seconds before invoking the pbstart command under the aegis of the pi user. The 15 second “nap” 🙂 gives time for the network to stabilize before the pbstart script connects to and begins to stream music.

Save the file and close leafpad. Finally, reboot your Pi.

$ sudo reboot

After the Pi finishes its boot cycle (and another 15 seconds after that), you should start hearing music streaming from Pandora automatically!

Troubleshooting in the future (if music does not play)

Sometime down the road, you may be faced with a situation where music does not play.  This could very well be caused by the fact that the “TLS fingerprint” associated with the Pandora website has expired. When Pandora updates their SSL certificates, a new TLS fingerprint is needed. Keep this in mind in the future when Patiobar stops working and you can’t figure out why. Revisit this section and update the TLS fingerprint as we will describe now.

First, run pianobar as a standalone program separate from Patiobar to verify this is the issue:

$ pianobar

If you do not hear music, but instead see an error message indicating a “TLS fingerprint mismatch”, proceed with the next steps to resolve this issue.

We first need to copy over a handy script included with the pianobar distribution to our current directory so we can retrieve the latest TLS fingerprint:

$ cp /usr/share/doc/pianobar/contrib/ .

Next, set the user execute bit to make sure we can run the script:

$ chmod u+x

Go ahead and invoke this script to retrieve the TLS fingerprint:

$ bash

You should see something like this: FC2E6AF49FC63AEDAD1078DC22D1185B809E7534

Next, edit the pianobar configuration file:

$ leafpad ~/.config/pianobar/config &

Replace the existing tls_fingerprint configuration parameter with the new TLS fingerprint obtained:

tls_fingerprint = FC2E6AF49FC63AEDAD1078DC22D1185B809E7534

Run pianobar to verify that it now works before issuing a pbstart to restart Patiobar:

$ pianobar

You should hear music playing and be back in business!


There you have it! We created an amazing Pandora player that can be controlled remotely from a mobile device. We can control our Pandora listening experience through a web interface. As a bonus, we can also start and stop our Pandora player through an SSH interface on a mobile device with a handy menu as well. We are ready to enjoy music with family and friends—and we learned some cool technology tricks in the process!

Follow @thisDaveJ (Dave Johnson) on Twitter to stay up to date with the latest tutorials and tech articles.

Additional articles

Controlling a Raspberry Pi from a Mobile Device with Bonus Menu Too
Beginner’s Guide to Installing Node.js on a Raspberry Pi
Connecting a Raspberry Pi Using an Ethernet Crossover Cable and Internet Connection Sharing
Upgrading to more recent versions of Node.js on the Raspberry Pi

Controlling a Raspberry Pi from a Mobile Device with Bonus Menu Too

rmain main

In my Beginner’s Guide to Installing Node.js on a Raspberry Pi, I equipped you with the knowledge needed to build an awesome Raspberry Pi system that could also run in a headless mode. We’re able to avoid a dedicated monitor, keyboard, and mouse, and this opens a whole new world of possibilities!

This brings us to today’s scenario: you’ve deployed your headless Raspberry Pi in the living room and connected it to your speaker system, soaking in the full stereo sound of your favorite music using pianobar, the console-based Pandora player. It’s eventually time for bed and you’re tired. Should you yank the power cord on your Raspberry Pi and call it a night? Probably not – you might risk corrupting the microSD card. Should you walk upstairs and re-open your laptop so you can SSH into the Pi and safety shut it down? That’s a lot of work! Wouldn’t it be fantastic if you could connect to your Pi from the mobile phone sitting next to you and issue that shutdown -h now command? Controlling your Pi from a mobile device could be very useful in other contexts too beyond listening to music such as IoT applications, computer vision systems, Magic Mirrors, etc.

In this guide, I will teach you how to control your Raspberry Pi from a mobile device. As a bonus, we will create a menu application to make it easier to issue commands since typing complicated command-line syntax on a small screen can prove to be challenging! Let’s jump right in! Continue reading

Node.js: Playing Sounds to Provide Notifications

playing sounds

In a previous tutorial, we learned how to send email notifications Using Nodemailer and Gmail. In today’s session, we will learn how to play sounds using Node.js. As a bonus, we will learn how to continue to play a sound until our notification has been acknowledged by pressing a key on the keyboard. How does that sound? 🙂 Enough bad puns! 🙂 Let’s get started! Continue reading

Upgrading to more recent versions of Node.js on the Raspberry Pi

upgrading nodejs

I’ve received questions from readers of my Beginner’s Guide to Installing Node.js on a Raspberry Pi wanting to know how to upgrade to more recent versions of Node.js on the Raspberry Pi.  The steps are quite easy and can be adapted to other Debian variants as well including Ubuntu.  I’m assuming you followed the steps in my Beginners’ Guide, especially under the “Install Node.js” section where we update the Raspbian/Debian package repository to include the Node.js binaries provided by NodeSource.  Let’s get started! Continue reading

Beginner’s Guide to Installing Node.js on a Raspberry Pi

Learning through Making (LTM) logo

This article has been updated to cover the installation of the latest version of Node at the time of this writing which is Node 7.x.

In this installment of our LTM (Learning through Making) series of Node.js tutorials, we’re going to get Node up and running on a Raspberry Pi 3 or Pi 2. With the Raspberry Pi 3, you won’t need to buy a separate USB Wi-Fi adapter. I’m focusing on the Raspberry Pi 3/Pi 2 rather than older versions such as the Raspberry Pi B+ since these are the latest models at the time of this writing.  The Raspberry Pi 3, for example, sports a 1.2 GHz quad-core ARMv8 chip with 1 GB of RAM versus the Raspberry Pi 1 Model B+’s 700 MHz single-core ARMv6 chip with 512 MB RAM.

The instructions provided here are for installing Node.js on a Pi 3 (ARMv8) or Pi 2 (ARMv7) rather than other models based on the ARMv6 chip such as the Raspberry Pi 1 Model B, Raspberry Pi Model B+ or the Raspberry Pi Zero.  A majority of this installation guide should still prove useful for other Raspberry Pi systems besides the Pi 3 and Pi 2; however, the final steps focused on the installation of Node.js will not work for these systems based on the older ARMv6 architecture.

This tutorial is useful for anyone wishing to successfully install a Raspberry Pi 3/Pi 2 system, even if they are not interested in Node.js since the Node.js installation happens in the final steps of the tutorial.  But, why would you not want to install Node.js? 🙂  Let’s get started! Continue reading

Connecting a Raspberry Pi Using an Ethernet Crossover Cable and Internet Connection Sharing

I’m preparing for an upcoming speaking engagement around the topic of using Node.js and the Raspberry Pi for IoT applications. While at home, I enjoy the luxury of being the owner of my network which provides complete freedom in network configuration. On the road, I will not have this luxury whether it is at a hotel or when speaking at the conference.

Raspberry PiHere’s the problem I am trying to solve. While on the road, I want to be able to connect my laptop to the Wi-Fi hotspot on my phone rather than utilizing the wireless network at the conference location which might be fraught with both security and reliability issues. I also want to be able to get my Raspberry Pi system on the Internet. Additionally, I need my Raspberry Pi and my laptop to reside on the same network so I can easily connect and share files back and forth. Finally, I need this to be easy and foolproof so I’m not sweating on stage and trying to tweak Raspbian network configuration settings in order to establish network connectivity.

How about you? You might also have a similar need if you are seeking to get your Raspberry Pi on the Internet at a hotel, university, or other venue such as a conference. I’m going to show you how you can get your Raspberry Pi on the network when you are not connected to your home network using an Ethernet crossover cable.

I have read a lot of guides on the Internet, but they involve way too many steps. Surely there must be a better way that requires minimal fuss? Absolutely! Let’s get started! Continue reading

Node.js IoT – Data Visualization of Sensor Values

Sensor Data Viz

In today’s article, we’re moving beyond printing numbers in the console and creating some data visualization plots in both the terminal and in a graphical window. We’re also going to have fun!  😀

Today, I’m going to make the inductive leap that you’re making all of this happen using a Raspberry Pi. You may be able to implement these amazing ASCII terminal plots in the Windows world using Bash on Windows, but I have not tested in that context.  In addition to Raspbian, these steps will also generally work for other Linux distros as well as OS X.  If you are not running Node.js on your Raspberry Pi, please see my Beginner’s Guide to Installing Node.js on a Raspberry Pi.  You can also see my article on Using Visual Studio Code with a Raspberry Pi if you are seeking to set up a development environment.  For this tutorial, the Leafpad text editor, installed by default with Raspbian, may suffice. Continue reading

Node.js IoT – Create Local Module for CPU Sensor

CPU Sensor Local Module

We’re back and ready to do some refactoring of our CPU sensor so we can learn about Node.js modules and how to create them.  Building small, focused modules is one of the key tenets of the Node.js philosophy as summarized in The Node Way:

Building small, single-purpose modules is at the heart of the Node.js philosophy. Borrowing from Unix, Node.js encourages composing the complex and powerful out of smaller, simpler pieces. This idea trickles down from entire applications (using the best tool for the job vs. a full suite) to how the tools themselves are built.

Continue reading

While I napped, we got a new apt – Debian apt command cheat sheet

aptI’m now awake, everyone!  I must have been asleep (and perhaps you were too) since the Debian apt ecosystem now includes an “apt” binary that vastly improves the way we interact with the Debian package management ecosystem.  You can now use the single apt executable instead of apt-get, apt-cache, etc. for many common use cases.  These are groundbreaking changes for the better! My hope is that this post will accelerate your productivity whether you are using Ubuntu, Raspbian, or one of the many other other Linux distros based on Debian.

Scenario: You want to install the cowsay package because you know that a Linux system is not complete without it. 🙂


Given this context, let’s get started using the new, simplified apt binary:

apt update

Updates the local APT package index, a database of available packages available from the central Debian repositories configured for your machine.  It is a good idea to run this command periodically, especially before installing packages or doing upgrades.  You will probably need to add a “sudo” before this command since higher privileges will be required to complete this operation.

apt list cow*

List all packages (whether installed on your system or not) containing the word “cow” followed by anything.  If you run “apt list cow", it will only find packages with an exact match of “cow”.

apt search cow

Searches for “cow” in both package names and descriptions and returns the package name and a brief description.  Note that you don’t need to use a wildcard with this command since it will find “cow” contained in strings such as “cowsay” and “cowbell”.

apt show cowsay

Shows package details including a detailed description. You can use wildcards, but this command works best if you specify the exact package name obtained from a command such as apt list above.

The following commands will most likely need to be prepended with “sudo“.  I am not including “sudo” to avoid line noise so we can focus on the essence of each of the commands.

apt install cowsay

Installs the cowsay package. As a bonus, the new apt command also includes a progress bar in your terminal so you can more easily visualize progress.

apt remove cowsay

This command will remove the cowsay package.  I’m not sure why you’ve ever want to remove this very essential package though. 😉

apt full-upgrade

This command upgrades your system by removing, installing, and upgrading packages.  This is typically the command most people will want to run to get their systems up to date.  It is often used with the “apt update" command and can be combined into one command as follows if you want to show off your command line prowess:

sudo apt update && sudo apt full-upgrade

apt upgrade

This command upgrades your system by installing and upgrading packages.  It will automatically install, but will not remove any packages.  The apt full-upgrade discussed previously will be the command of choice for most in doing upgrades.


With these simple commands above as a reference, you should be able to accomplish 99% of what you need to work with packages in the Debian Linux world.  Spread the word about these new apt command options.  They are quite handy!

Follow @thisDaveJ on Twitter to stay up to date on the latest tutorials and tech articles.

Related Articles

Beginner’s Guide to Installing Node.js on a Raspberry Pi

Node.js IoT – Build a Cross Platform CPU Sensor

cross platform cpu sensor

I took a little hiatus in our series to take my family on a trip to Japan with layovers on each end of the trip in China which included a ride on the Shanghai Maglev Train, the fastest train in the world.  We had a fantastic time, and it was a great educational experience for the kids.  It is also good to be back home!

We are back again with our Node.js IoT tutorial series and ready to continue developing our “CPU sensor” as CPU loading/utilization is a “sensor” we can measure, record, and ultimately stream to other locations.  Today, we will expand our CPU sensor and make it cross platform—and learn more about Node.js in the process. In future tutorials, we will harness the power of Node.js to interact with physical sensors that live outside of our computing environment.  Continue reading