Skip to main content

Operations

Day-to-day management of a running station.

Checking Status

Quick status — what's playing, are services up:

systemctl status mpd icecast2 nginx pi3radio song-logger
mpc status

The web UI also shows a health indicator (green/amber/red dot) in the header, backed by the /api/health endpoint which reports load, disk, NAS mount status, and service states.

Deploying Changes

All changes are deployed from your development machine — never edit files directly on the Pi. The workflow:

  1. Make changes locally
  2. Test in staging (mock data mode, no API keys needed)
  3. Promote to production
# Push to staging (port 8080, mock data)
rsync -av staging/ pi-user@your-pi:/var/www/radio-staging/

# Promote staging to production
cp -r staging/ public/
rsync -av public/ pi-user@your-pi:/var/www/radio/public/

# Deploy backend changes
rsync -av server/ pi-user@your-pi:/var/www/radio/
ssh pi-user@your-pi "sudo systemctl restart pi3radio"

Restarting Services

Restart the Python API and reload Nginx:

sudo systemctl restart pi3radio
sudo systemctl reload nginx

Restart MPD (will briefly interrupt the stream):

sudo systemctl restart mpd

Recovery After Power Loss

After a power cut or reboot, the NAS mount may not come back automatically. Run this sequence:

sudo mount -a # remount NAS
sudo systemctl restart mpd # restart MPD
/usr/local/bin/radio_scheduler.sh # re-run scheduler to resume programming

Log Files

LogContents
/var/log/radio_playlist.logEvery song played (4 lines per song)
/var/log/radio_schedule.logHourly scheduler decisions
/var/log/mpd/mpd.logMPD errors and events
/var/log/icecast2/error.logIcecast errors
/var/log/nginx/error.logNginx errors

Tail the song log live:

tail -f /var/log/radio_playlist.log

Last 20 songs played:

grep "NOW PLAYING" /var/log/radio_playlist.log | tail -20

Database Backups

Pull a copy of the database to your local machine:

rsync pi-user@your-pi:/var/www/radio/db.sqlite3 ./backups/db_$(date +%Y%m%d_%H%M%S).sqlite3

Query tagged songs from a local backup:

sqlite3 backups/db_latest.sqlite3 \
"SELECT s.artist, s.title, t.tag FROM songs s JOIN tags t ON s.id = t.song_id ORDER BY t.tag, s.artist;"

Song Tagging

The web UI lets you tag any song in the recent playlist. Tags are stored in SQLite and used by the scheduler and stats views.

TagEffect
FavouriteMarks the song as a keeper
ReviewFlag to listen again before deciding
LiveMarks as a live recording
Bad MP3Flags poor quality rips
DuplicateFlags duplicates in the library
EjectAdds to exclude list — never plays again

Useful API Calls

# What's playing right now
curl http://your-pi/api/playlist | python3 -m json.tool

# System health
curl http://your-pi/api/health | python3 -m json.tool

# All favourites
curl "http://your-pi/api/tags?tag=Favourite"

# Export full play history as CSV
curl http://your-pi/api/export -o plays.csv

Keyboard Shortcuts

The web player supports keyboard shortcuts when focused in a browser:

KeyAction
SpacePlay / pause
Skip to next track
FTag current track as Favourite
RTag current track as Review
LTag current track as Live