Raspberry Pi Car Media Server v2.0 [gav-pi11]
After many years of reliable service from the original Car Media Server, it started glitching, i.e. the spinning rust was causing it to crash - well it had been over thousands of speed bumps, and I was surprised at how well it survived!
So, since this is an upgrade to solid state, I thought that I'd take the chance to upgrade the Pi too - to a Pi 3: faster (although the original Pi was able to supply music and stream to 4 devices simultaneously, so not really an issue!), more USB ports (to save having to use an external hub), and (more importantly) built-in Wi-Fi!
Page Contents (well, it's a big one after all!):
- What is it & why do it?
- Parts List
- Connector Pin-Out
- Initial setup
- Configuring the Wi-Fi Hotspot
- Configuring DHCP / DNS
- Configuring a 3G / 4G USB Modem
- Configuring IP Forwarding & Network Address Translation (NAT)
- Mounting the flash drive(s)
- Configuring Music Player Daemon (MPD)
- Configuring MiniDLNA
- Configuring nfs-kernel-server
- Configuring the Power Circuitry
- GPIO Permissions
- Automatic Random Tracks
- The Magic Button
- Specifications
- Helpful resources
What is it & why do it?
This car media server allows the streaming of video and audio to devices in the car, and allows any connected devices access to the Internet.
Why? Well there were many, many long journeys in the car with bored kids in the back who would eventually start playing up. We decided that a simple way to keep them quiet (after eye-spy with colours ran its course - let's face it: when travelling in the rain, most things are grey!), was to let them watch the films and TV shows that they have access to from the home server (via our media PC). Also, it would allow us access to our entire CD collection (albeit with lossy compressed mp3s) at the touch of a button.
Why not just use an off-the-shelf in-car Wi-Fi / 3G / Media server? Well, it comes down to a couple of reasons:
- The kids (at the time) couldn't read, so using this method, the films can be selected from a remote control - made possible as the server will give the devices the same IP address as it's also a DCHP and DNS server, and will allow Kodi (on the tablets) to mount the server's file system, and not just use UPnP / DLNA.
- I'm a geek, so wanted a(nother) Raspberry Pi project ;-)
Parts List
Item Description | Vendor | Part Number | Qty |
---|---|---|---|
Raspberry Pi 3 (Available from lots of places) |
Amazon
CPC (Farnell) Pimoroni RS The Pi Hut |
1 | |
Mausberry Circuits, 3A car supply | Mausberry | 3A car circuit | 1 |
Multicomp MB5, plastic enclosure, 150x100x60mm | Farnell | 301280 | 1 |
Lumberg KV120, 12-way DIN cable mount jack | Farnell | 1243258 | 1 |
Lumberg SFV120, 12-way DIN panel mount plug | Farnell | 1193063 | 1 |
TE Connectivity MSPS103B, pushbutton switch | Farnell | 1703861 | 1 |
Neutrik NTP3RC-B 3.5mm right-angled stereo plug | Farnell | 5008414 | 1 |
Neutrik NYS240BG 3.5mm stereo socket (optional) | Farnell | 1390177 | 1 |
M2.5 Standoffs for Pi HATs - black plated - pack of 2 | Pimoroni | COM2100 | 2 |
8P8C panel mount extension | The Pi Hut | Adafruit 909 | 1 |
Sandisk Ultra micro-SD card, 8GB (root filesystem) | Amazon | 1 | |
Sandisk UltraFit USB 3 flash drive, 64GB (music) | Amazon | 1 | |
Sandisk UltraFit USB 3 flash drive, 128GB (videos) | Amazon | 1 |
Depending on how you connect to the car stereo, you may want to order another 3.5mm right angled stereo jack plug, or perhaps the socket listed.
Connector Pin-Out
This is really more for my own use, but feel free to use the same pin-out (assuming that you use the same connector). There are several reserved pins - I wanted as many as possible (without going overboard) to cover any future needs.
The external Ethernet port is simply to make my life easier when it comes to adding media to the server - bring it into the house and plug it into the switch in my computer room... without having to remove the cover, like I had to do with the last car server!
Pin | Signal | Description | Pi Pin |
---|---|---|---|
A | BATT | Permanent (battery) 12V (yellow) | N/A |
B | ACC | Accessory 12V (red) | N/A |
C | GND | Ground (black) | N/A |
D | N/C | Reserved (brown jumper) | 12 (GPIO18) |
E | Audio Right | Audio right channel | 3.5mm Jack |
F | Audio Rtn | Audio return | 3.5mm Jack |
G | Audio Left | Audio left channel | 3.5mm Jack |
H | Button | Pushbutton input (yellow jumper) | 7 (GPIO4) |
J | Button Rtn | Pushbutton return (ground - green jumper) | 9 (GND) |
K | N/C | Reserved (blue jumper) | 11 (GPIO17) |
L | N/C | Reserved (red jumper) | 3 (SDA1) |
M | N/C | Reserved (orange jumper) | 5 (SCL1) |
You may notice that the I2C bus is connected - well, you never know what future additions may happen ;-)
Initial setup
- Plug an SDHC card into desktop PC (or laptop).
- Download and install Raspbian to the card (the following instructions are based upon "stretch").
-
Plug the SDHC card into the Raspberry Pi and power up. Set up everything
required from the configuration application (hostname, SSH, default sound
output etc.)
sudo raspi-config
-
If you've bought the CODECs for MPG2 and WVC1, then now is as good a
time as any to set them up. Edit /boot/config.txt
sudo nano /boot/config.txt
-
Add the license keys that you received from the Raspberry Pi Store,
something like this
decode_MPG2=0x01234567
decode_WVC1=0x89abcdef -
At some convenient time after a reboot, verify that they are enabled
vcgencmd codec_enabled MPG2
vcgencmd codec_enabled WVC1 -
From the desktop PC, SSH into the Raspberry Pi and upgrade the system
sudo apt-get update
sudo apt-get upgrade
Configuring the Wi-Fi Hotspot
We're going to use the Pi 3's built-in Wi-Fi for providing the hotspot.
-
Install host access point daemon
sudo apt-get install hostapd
-
Set up wlan0 for static IP
sudo nano /etc/dhcpcd.conf
-
and add the following lines
interface wlan0
static ip_address=192.168.100.1/24 -
Assign the IP address to wlan0
sudo ifconfig wlan0 192.168.100.1
-
Create a new access point configuration file with
sudo nano /etc/hostapd/hostapd.conf
-
Copy (and modify to suit) the following into the file
interface=wlan0
driver=nl80211
ssid=Car_WiFi
hw_mode=g
ieee80211n=1
wmm_enabled=1
channel=8
ignore_broadcast_ssid=0
own_ip_addr=192.168.100.1
macaddr_acl=0
auth_algs=1
wpa=2
wpa_passphrase=raspberry-pi
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP -
Point the daemon to the configuration file by editing /etc/default/hostapd
sudo nano /etc/default/hostapd
-
Changing the line
#DAEMON_CONF=""toDAEMON_CONF="/etc/hostapd/hostapd.conf"
-
Test the setup
sudo /usr/sbin/hostapd /etc/hostapd/hostapd.confand try to connect with a mobile device.
It will get stuck "Obtaining IP address" since we've no DHCP server yet, but the terminal should show some useful output. [Ctrl] [c] to exit.
You may need to re-apply the IP address of wlan0 at this point since hostapd removes it when it stops. -
Start the hostapd daemon
sudo service hostapd start
Configuring DHCP / DNS
-
Install the software
sudo apt-get install dnsmasq
-
Configure dnsmasq
sudo nano /etc/dnsmasq.conffor exampleinterface=wlan0
domain=carwifi.net
dhcp-range=192.168.100.200,192.168.100.250,2h
read-ethers -
Create the file /etc/ethers
sudo nano /etc/ethersand add the MACs of any known devices that you want to find by name on the network - tablets and phones for example.
-
Edit the file /etc/hosts
sudo nano /etc/hostsand add the IP addresses and names of the same phones and tablets.
-
Restart the dnsmasq daemon
sudo service dnsmasq restart
- Try to connect with a mobile device... it should just work!
Configuring a 3G / 4G USB Modem
This turns out to be far simpler that first thought. Even though the modem used is a multi-device type (i.e. "CD-ROM" as well as a modem), the community has it all covered. Simply installing a couple of packages from the repository was all that was required.
-
Install "usb_modeswitch" (although it is probably already there)
sudo apt-get install usb-modeswitch
-
Install Network Manager
sudo apt-get install network-manager
-
Plug in the modem and after 20 seconds or so, type
ifconfigand you should see a new network device.
Of course, as it turns out, not all USB modems are made equal - at least old and new ones. It's been pointed out to me that newer modems may not just work "out of the box" as mine did, so you may have to compile the USB Mode Switch from source, with the updated data - as the Raspbian package may not be new enough.
Configuring IP Forwarding & Network Address Translation (NAT)
If you plan on adding a 3G or 4G modem, then this is definitely required. If not, then it's still handy to set up IP forwarding for those times that the server is out of the car and connected to the house network.
-
Enable IPv4 forwarding by editing /etc/sysctl.conf
sudo nano /etc/sysctl.conf
-
Change the line
#net.ipv4.ip_forward=1tonet.ipv4.ip_forward=1
-
That won't come into effect until a reboot, so set it manually now
sudo sysctl net.ipv4.ip_forward=1
-
Edit /etc/rc.local with IP Tables for NAT'ing (if required) behind a
3G / 4G modem
sudo nano /etc/rc.local
-
Add the following lines before "exit 0"
sudo iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADEIf you don't have a 3G / 4G modem, replace usb0 with eth0 above.
sudo iptables -A FORWARD -i usb0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o usb0 -j ACCEPT -
Reboot the Pi to check that it all works. You should now be able
to connect a wireless device and surf the web (assuming that you have
the 3G / 4G modem plugged in or the Ethernet port connected to an active
Internet connection).
sudo reboot
Mounting the flash drive(s)
- Plug in the USB flash drive(s).
-
Locate the flash drive(s):
ls -l /dev/disk/by-uuid/The drive(s) will [most likely] start on /dev/sda1:ABCD-1234 -> ../../sda1
FEDC-9876 -> ../../sda2 -
Create a mount point for the drive(s)
sudo mkdir /home/music
sudo mkdir /home/videos -
Mount a drive (for a test)
sudo mount -t vfat -o uid=pi,gid=pi /dev/sda1 /home/music/
-
Now make it permanent by editing /etc/fstab
sudo nano /etc/fstab
-
Add this line to the end of the file
UUID=ABCD-1234 /home/music vfat rw,nosuid,noexec,noatime,uid=1000,gid=1000 0 0
UUID=FEDC-9876 /home/videos vfat rw,nosuid,noexec,noatime,uid=1000,gid=1000 0 0
Configuring Music Player Daemon (MPD)
-
Install MPD
sudo apt-get install mpd
-
Configure /etc/mpd.conf to suit network / music setup (the default ALSA
output should be good as it is)
sudo nano /etc/mpd.conf
-
Restart MPD
sudo service mpd restart
- Make sure everything works with your favourite Music Player Client
Configuring MiniDLNA
Just in case you don't actually want to run Kodi to render video, this will serve any DLNA / UPnP renderer.
-
Install minidlna
sudo apt-get install minidlna
-
Configure /etc/minidlna.conf to suit network / music setup
sudo nano /etc/minidlna.conf
-
Restart MiniDLNA
sudo service minidlna restart
Configuring nfs-kernel-server
It appears that Kodi / Kodi Remote control (Kore) won't let you select videos for playing that are not on a local file system (e.g. served from a UPnP server), so let's create NFS mount points for the media.
-
Install nfs-kernel-server
sudo apt-get install nfs-kernel-serverNote that if it fails, try removing nfs-common and rpcbind and then install all 3 at the same time.
-
Add an export point to /etc/exports
sudo nano /etc/exports
-
Add the following lines to make /home/music and /home/videos read only to the
whole sub-net serviced by the Pi:
/home/music 192.168.100.0/24(ro,insecure,no_subtree_check,async)
/home/videos 192.168.100.0/24(ro,insecure,no_subtree_check,async) -
Restart the nfs-kernel-server
sudo service nfs-kernel-server restart
Configuring the Power Circuitry
Since this is a Linux system, it really doesn't like to get it's power forcibly removed from it (as no modern operating systems do).
So, I got hold of a wee power supply designed for car use. It powers up when the ignition switch in in the "accessory" position and signals the Pi to power down after it has been removed. Only when the Pi has fully shut down will the power be removed.
It is set up as described on Mausberry Circuit's setup page.
GPIO Permissions
This is something that I must have forgotten to document with the old server. Basically from boot, you don't have the correct permissions to write to the GPIO. If the "switch.sh" is run as "sudo" from a terminal then it all works fine.
So after a lot of Googling, and using this page as a guide, I did this:
-
Edit the Raspbian udev rules
sudo nano /etc/udev/rules.d/99-com.rules
-
Change the GPIO entry from this:
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\to this:
chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/v$
chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
chown -R pi:pi /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
chown -R pi:pi /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/v$
chown -R pi:pi /sys$devpath && chmod -R 770 /sys$devpath\
'"
After that, the user "pi" should always be able to read / write from / to the GPIO.
Automatic Random Tracks
Of course, the trouble with having a music system that relies on a mobile phone or tablet to get something playing soon becomes apparent when there is nobody but the driver in the car... how do you play music if the radio is not acceptable?
What you do is write yourself a wee script that checks whether or not there is a track playing, and adds a random track if there isn't!
This process has been split into two scripts: one to create the playlist from which to pick tracks (which will be run once during boot), and another to load up MPD with random tracks.
-
Install MPC (Music Player Client)
sudo apt-get install mpc
-
Create the first magic script:
nano ~/mpd_track_list.sh
-
Enter (and modify to suit) the following code (note that you can easily
remove bands, albums, or even song titles with swear words - for the sake of
the kids' ears - I've *'ed out some letters here though to make it web
friendly, but you'll get the idea):
#!/bin/bash
# Define the path and any password options for MPD
MY_MPC="/usr/bin/mpc -h 192.168.100.1"
# Define acceptable genres of random tracks to add
MY_GENRES="Electronica Folk Funk Indie Jazz Pop Reggae Rock Soul Soundtrack"
# Define Anything to strip out
MY_STRIP="Wiggles F*** S***"
# Remove the track list file if it exists
rm -f /tmp/random_mpd_tracks.txt
for genre in ${MY_GENRES}
do
$MY_MPC search genre ${genre} >> /tmp/random_mpd_tracks.txt
done
for strip in ${MY_STRIP}
do
grep -v -i ${strip} /tmp/random_mpd_tracks.txt > /tmp/random_mpd_tracks_out.txt
mv /tmp/random_mpd_tracks_out.txt /tmp/random_mpd_tracks.txt
done -
Create the second magic script:
nano ~/random_mpd_tracks.sh
-
Enter (and modify to suit) the following code:
#!/bin/bash
# Define the path and any password options for MPD
MY_MPC="/usr/bin/mpc -h 192.168.100.1"
while [ 1 ]; do
# Check if MPD is up and running
$MY_MPC status
if [ $? -eq 0 ]; then
# We're alive, so let's play
# First let's see how many tracks are in the playlist
number_of_tracks=`$MY_MPC playlist | wc -l`
# If we have less than 2 tracks playing, add random(s)
# Why 2? Well it ensures no break in the music
if [ $number_of_tracks -lt 2 ]; then
# How many tracks needed?
number_to_add=`expr 2 - $number_of_tracks`
random_tracks=`cat /tmp/random_mpd_tracks.txt | shuf -n $number_to_add`
# Add it to the play list
$MY_MPC add $random_tracks
fi
# Set up the playing style
$MY_MPC -q single off
$MY_MPC -q random off
$MY_MPC -q repeat off
$MY_MPC -q consume on
# Press "play" :-)
$MY_MPC -q play
fi
sleep 10
done -
Make both scripts executable:
chmod +x ~/mpd_track_list.sh
chmod +x ~/random_mpd_tracks.sh -
Launch the commands at boot by adding them to /etc/rc.local:
sudo nano /etc/rc.local
-
Add the following lines at the end of the file (before "exit 0"):
# Launch the MPD Random Track Generator
/home/pi/mpd_track_list.sh
/home/pi/random_mpd_tracks.sh &
Note: there may be slightly later versions of the scripts on my useful scripts page.
The Magic Button
Up until now, you may have been wondering what that pushbutton switch is for, well think of all of the times that a random track has come on that you just don't like, or are just not in the mood for... well now you can easily skip it by pressing the button (otherwise, you'd need to have a music player client running on a phone or tablet - not advisable if you're driving!)
The switch itself needs to be installed in an easy to reach location on the car's dashboard or centre console. Then, you need another magic script to make it useful. Note that this script performs the following:
- Press (press ≤ 350ms): skip track
- Long press (350ms < press ≤ 2000ms): repeat track
- Press and hold (press ≥ 5000ms): reboot... just in case things go pear-shaped.
-
Create the magic button script:
nano ~/magic_button.sh
-
Enter (and modify to suit) the following code:
#!/bin/bash
# Define the path and any password options for MPD
MY_MPC="/usr/bin/mpc -h 192.168.100.1"
# This is the GPIO pin connected to the magic button
MagicButton=4
echo "$MagicButton" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio$MagicButton/direction
old=0
start=0
end=0
diff=0
while [ TRUE ]; do
button=$(cat /sys/class/gpio/gpio$MagicButton/value)
uptime=$(</proc/uptime)
uptime=${uptime%% *}
uptime=${uptime/.}
#echo "MagicButton: ${button} ${old} ${uptime} ${start} ${end} ${diff}"
# Check for button state
if [ ${button} -eq 1 ] && [ ${old} -eq 0 ]; then
# Button pressed
old=1
start=${uptime}
fi
if [ ${button} -eq 0 ] && [ ${old} -eq 1 ]; then
# Button released
old=0
end=${uptime}
diff=`expr ${end} - ${start}`
# Now act on the length of button press
if [ ${diff} -le 35 ]; then
# Skip track
echo "MagicButton: Skipping track"
$MY_MPC -q next
fi
if [ ${diff} -gt 35 ] && [ ${diff} -le 200 ]; then
# Restart track
echo "MagicButton: Restarting track"
$MY_MPC -q seek 00:00:00
fi
if [ ${diff} -ge 500 ]; then
# Reboot
echo "MagicButton: Rebooting server"
reboot
fi
fi
sleep 0.1
done -
Make the script executable:
chmod +x ~/magic_button.sh
-
Launch the command at boot by adding it to /etc/rc.local:
sudo nano /etc/rc.local
-
Add the following lines at the end of the file (before "exit 0"):
# Launch the Magic Button
/home/pi/magic_button.sh &
Note: there may be a slightly later version of the script on my useful scripts page.
Specifications:
Case: | Multicomp MB5 Plastic Enclosure | ||||
Power Supply: | 3A Car Supply / Switch from Mausberry Circuits | ||||
Board: | Rapsberry Pi 3B+ (version 1.0) | ||||
SoC: |
Broadcom BCM2837B0
|
||||
RAM: | 1GiByte LPDDR2 SDRAM | ||||
Storage: |
Sandisk
Ultra, class 10 (8GByte micro SDHC - root filesystem)
Sandisk Ultra Fit (64GByte USB 3.0 - music) Sandisk Ultra Fit (128GByte USB 3.0 - videos) |
||||
USB Modem: | Huawei E3372 (4G) | ||||
Speakers: | Car audio system | ||||
Monitor: | None | ||||
Keyboard / Mouse: | None |
Helpful resources:
- RaspBMC OS X / Linux installation
- Installing nfs-kernel-server (Raspbmc forum on Stm Labs)
-
Raspberry
Pi as an Ad Blocking Access Point
(note: change http to https in "ad_list_url" or it won't work) - Setting udev rules for GPIO
- Setting up a Raspberry Pi as a WiFi access point
- Using your new Raspberry Pi 3 as a WiFi access point with hostapd
- Why is my Audio (Sound) Output not working?
- WiFi Access Point
Computing Power
- Acer Aspire R3700
- Acknowledgements
- BOINC
- Desktop PC
- Eee PC 4G (701)
- Eee PC 901
- Gigabit Network
- Inspiron 14 5485 Laptop
- Kids PC 1
- Kids PC 2
- Media PC
- Mini-ITX PC
- My Useful Scripts
- Nano ITX PC
- Nook Simple Touch
- Processing Power
- Raspberry Pi
- Sharp Zaurus SL-C3200
- Storage Capacity
- The Server
- What Is Firmware