Raspberry Pi Car Media Server v2.0 [gav-pi11]

Pi Car Media Server v2.0

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!):

  1. What is it & why do it?
  2. Parts List
  3. Connector Pin-Out
  4. Initial setup
  5. Configuring the Wi-Fi Hotspot
  6. Configuring DHCP / DNS
  7. Configuring a 3G / 4G USB Modem
  8. Configuring IP Forwarding & Network Address Translation (NAT)
  9. Mounting the flash drive(s)
  10. Configuring Music Player Daemon (MPD)
  11. Configuring MiniDLNA
  12. Configuring nfs-kernel-server
  13. Configuring the Power Circuitry
  14. GPIO Permissions
  15. Automatic Random Tracks
  16. The Magic Button
  17. Specifications
  18. 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.

Pi Car Media Server v2.0
Pi Car Media Server v2.0

Pi Car Media Server v2.0
Pi Car Media Server v2.0

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:

  1. 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.
  2. I'm a geek, so wanted a(nother) Raspberry Pi project ;-)

Parts List

Pi Car Media Server v2.0 Bits

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

Pi Car Media Server v2.0

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

  1. Plug an SDHC card into desktop PC (or laptop).
  2. Download and install Raspbian to the card (the following instructions are based upon "stretch").
  3. 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
  4. 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
  5. Add the license keys that you received from the Raspberry Pi Store, something like this
    decode_MPG2=0x01234567
    decode_WVC1=0x89abcdef
  6. At some convenient time after a reboot, verify that they are enabled
    vcgencmd codec_enabled MPG2
    vcgencmd codec_enabled WVC1
  7. 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.

  1. Install host access point daemon
    sudo apt-get install hostapd
  2. Set up wlan0 for static IP
    sudo nano /etc/dhcpcd.conf
  3. and add the following lines
    interface wlan0
    static ip_address=192.168.100.1/24
  4. Assign the IP address to wlan0
    sudo ifconfig wlan0 192.168.100.1
  5. Create a new access point configuration file with
    sudo nano /etc/hostapd/hostapd.conf
  6. 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
  7. Point the daemon to the configuration file by editing /etc/default/hostapd
    sudo nano /etc/default/hostapd
  8. Changing the line
    #DAEMON_CONF=""
    to
    DAEMON_CONF="/etc/hostapd/hostapd.conf"
  9. Test the setup
    sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf
    and 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.
  10. Start the hostapd daemon
    sudo service hostapd start

Configuring DHCP / DNS

  1. Install the software
    sudo apt-get install dnsmasq
  2. Configure dnsmasq
    sudo nano /etc/dnsmasq.conf
    for example
    interface=wlan0
    domain=carwifi.net
    dhcp-range=192.168.100.200,192.168.100.250,2h
    read-ethers
  3. Create the file /etc/ethers
    sudo nano /etc/ethers
    and add the MACs of any known devices that you want to find by name on the network - tablets and phones for example.
  4. Edit the file /etc/hosts
    sudo nano /etc/hosts
    and add the IP addresses and names of the same phones and tablets.
  5. Restart the dnsmasq daemon
    sudo service dnsmasq restart
  6. 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.

  1. Install "usb_modeswitch" (although it is probably already there)
    sudo apt-get install usb-modeswitch
  2. Install Network Manager
    sudo apt-get install network-manager
  3. Plug in the modem and after 20 seconds or so, type
    ifconfig
    and 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.

  1. Enable IPv4 forwarding by editing /etc/sysctl.conf
    sudo nano /etc/sysctl.conf
  2. Change the line
    #net.ipv4.ip_forward=1
    to
    net.ipv4.ip_forward=1
  3. That won't come into effect until a reboot, so set it manually now
    sudo sysctl net.ipv4.ip_forward=1
  4. Edit /etc/rc.local with IP Tables for NAT'ing (if required) behind a 3G / 4G modem
    sudo nano /etc/rc.local
  5. Add the following lines before "exit 0"
    sudo iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADE
    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
    If you don't have a 3G / 4G modem, replace usb0 with eth0 above.
  6. 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)

  1. Plug in the USB flash drive(s).
  2. 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
  3. Create a mount point for the drive(s)
    sudo mkdir /home/music
    sudo mkdir /home/videos
  4. Mount a drive (for a test)
    sudo mount -t vfat -o uid=pi,gid=pi /dev/sda1 /home/music/
  5. Now make it permanent by editing /etc/fstab
    sudo nano /etc/fstab
  6. 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)

  1. Install MPD
    sudo apt-get install mpd
  2. Configure /etc/mpd.conf to suit network / music setup (the default ALSA output should be good as it is)
    sudo nano /etc/mpd.conf
  3. Restart MPD
    sudo service mpd restart
  4. 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.

  1. Install minidlna
    sudo apt-get install minidlna
  2. Configure /etc/minidlna.conf to suit network / music setup
    sudo nano /etc/minidlna.conf
  3. 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.

  1. Install nfs-kernel-server
    sudo apt-get install nfs-kernel-server
    Note that if it fails, try removing nfs-common and rpcbind and then install all 3 at the same time.
  2. Add an export point to /etc/exports
    sudo nano /etc/exports
  3. 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)
  4. 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:

  1. Edit the Raspbian udev rules
    sudo nano /etc/udev/rules.d/99-com.rules
  2. Change the GPIO entry from this:
    SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
      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\
    '"
    to this:
    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.

  1. Install MPC (Music Player Client)
    sudo apt-get install mpc
  2. Create the first magic script:
    nano ~/mpd_track_list.sh
  3. 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
  4. Create the second magic script:
    nano ~/random_mpd_tracks.sh
  5. 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
  6. Make both scripts executable:
    chmod +x ~/mpd_track_list.sh
    chmod +x ~/random_mpd_tracks.sh
  7. Launch the commands at boot by adding them to /etc/rc.local:
    sudo nano /etc/rc.local
  8. 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.
  1. Create the magic button script:
    nano ~/magic_button.sh
  2. 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
  3. Make the script executable:
    chmod +x ~/magic_button.sh
  4. Launch the command at boot by adding it to /etc/rc.local:
    sudo nano /etc/rc.local
  5. 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
CPU: 64-bit Quad-core (ARM Cortex-A53, ARMv8-A arch) @ 1.4Ghz
GPU: Broadcom VideoCore IV @ 400 MHz
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:




Del.ico.us Digg Facebook Google LinkedIn LiveJournal NewsVine reddit StumbleUpon Twitter
Valid XHTML 1.0 Transitional Valid CSS! [Valid Atom 1.0] [Valid RSS 2.0]
[ Page last updated Sat 15th Apr 2023 | viewed 6784 times ]