Raspberry Pi Internet Radio
Nachdem das Internetradio auch nach Reparatur ganz schnell wieder hinüber war, der Versuch ein Internetradio mit dem "herumliegenden Pi" umzusetzen.
Ich ging davon aus, dass es mit Standardkomponenten geht, war aber nicht ganz so. Es gibt sehr
viele Anleitungen, die berichten, wie man den mpd (Music Player Daemon) auf dem Pi aufsetzt, beim Interface
habe ich nichts passendes gefunden.
Möchte man mpd für die eigene Musiksammlung nutzen, dann ist als Userinterface ympd sehr gut geeignet.
Scheint mir schlank und sehr schnell zu sein. Die Verwaltung von Radiosendern läuft aber über Playlists und
selbst wenn man auf mpd 0.19 aktualisiert und damit pls Dateien und extended m3u unterstüzt werden, werden
sender nur unschön angezeigt.
Daher wurde ein Webinterface entwickelt, dass ausschließlich Radio-Sender verwaltet. Statt der Playlist des mpd werden die Daten in einer sqlite db-Datei vorgehalten.
Außerdem ist eine kleine Wrapper Klasse um das Web-Protocol des mpd verwendet worden, dies findet sich auf Github. Der Source-Code wurde in das vorliegende Projekt übernommen.
Aktualisierung der Anzeige
Ändert sich die Informationen, die ein Sender neben dem mp3-Stream weiter gibt, aktualisiert mpd den Titel. Dieser wird vom Interface angezeigt. Daher sollte ein regelmäßer Austausch zwischen Server und Client statt finden. Mögliche Lösungen sind meines Wissens WebSockets, Server Sent Events (SSE), eventuell Comet und Polling.
Empfehlenswert sind sicherlich Websockets, es gibt eine php-Bibliothek, der anfängliche Aufwand schien mir für ein Projekt jedoch zu hoch. Zudem ist mir nicht klar, ob der epiphany Browser auf dem Raspberry diese unterstützt. (Ein Browser auf dem Pi ist eventuell sinnvoll, da ich noch ein TFT Display habe, dass die Anzeige übernehmen könnte – vielleicht später mal. Dazu ein paar Taster und man könnte das Radio auch ohne Smartphone bedienen).
Server Sent Events waren zunächst viel versprechend. Keine bidirektionale Kommunikation, aber der Server sendet an den Client und für Client-Anfragen (Umschalten des Senders) können ja weiterhin Ajax-Requests verwendet werden. Leider benötigten die Ajax-Requests dann bis zu einer Minute, normal waren 150ms. Die Ursache ist mir nicht klar, selbst wenn die SSE Verbindung unterbrochen wurde, bevor der Ajax-Request abgesendet wurde, blieb das Problem bestehen - schade, komplett unverstanden. Falls jemand das Problem versteht - Aufklärung ist gern gesehen :-). (Die Code-Versuche finden sich auf github im Branch developmentServerSentEvents.)
Also Polling. Neben den Ajax-Requests um die Sender anzuzeigen, umzuschalten, Start/Stop und das Ändern der Lautstärke wird jede Sekunde ein Request gesendet, der den Status abfragt. Dabei wird auch die aktuell angezeigte Seite übermittelt, so dass der Client seine Ansicht aktualisiert. Soll ein Steuersignal an den Raspi gesendet werden, wird die sekündliche Abfrage unterbrochen und wieder aufgenommen, wenn der durch den Benutzer ausgelöste Request abgearbeitet ist. Nicht sehr elegant, funktioniert aber und weder der Raspi noch ein älteres Smartphone waren überfordert.
Installation
Die Installation des mpd ist an vielen Stellen beschrieben (sowohl auf deutsch als auch auf englisch), z.B. bei der Linux User Group Saar. Nur das dort empfohlene Webinterface ist durch mein "eigenes" ausgetauscht. Dieses findet man auf Github.Steuerung
Die Steuerung kann über das Web-Interface, eine Pebble
und die fhem Oberfläche erfolgen das Modul findet sich ebenfalls auf github im Ordner fhemScreenshots
... dazu war ich nun zu faul - einen Eindruck bekommt man hier
Optimierungen
Den Rechner habe ich zwar schon öfter einfach so vom Strom genommen. Dennoch ist ein Risiko des Datenverlust, meines Wissens bis zum defekten Dateisystem möglich.Daher bietet sich ein Readonly-Dateisystem ein. Man findet diverse Informationen im Netz, ich habe eine Anleitung der ct 21/2016 grob befolgt. Im Wesentlichen (bessere Lösung unten):
- Dateisystem readonly setzen und einige Verzeichnisse auf eine ram-Disk setzen, meine fstab sieht so aus:
proc /proc proc defaults 0 0 /dev/mmcblk0p7 /boot vfat defaults,ro 0 2 /dev/mmcblk0p8 / ext4 defaults,noatime,ro 0 1 tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=1777,size=10m 0 0 #ct sagt tmpfs /var/tmp tmpfs nodev,nosuid,mode=1777,size=10m 0 0 tmpfs /tmp tmpfs nodev,nosuid,mode=1777,size=10m 0 0 #tmpfs /var/run tmpfs defaults,noatime,nosuid,mode=0755,size=10m 0 0 #tmpfs /run tmpfs defaults,noatime,nosuid,mode=0755,size=5m 0 0 #run on tmpfs by default?, var run geht auch nicht # a swapfile is not a swap partition, so no using swapon|off from here on, use dphys-swapfile swap[on|off] for that
- Die CT empfiehlt noch einige Dateien zu kopieren bzw. Sym-links zu setzen, das habe ich gelassen.
- Die Datenbank des mpd muss kopiert werden, dazu die Datei /etc/init.d/mpd leicht ergänzt.
mpd_start () { mkdir -p /var/log/mpd cp /var/lib/mpd/database /var/log/mpd/ chown mpd /var/log/mpd/database ...
-
Der Webserver lighttpd benötigt das Log-Verzeichnis /var/log/lighttpd, daher im Startskript des Lighttpd
case "$1" in start) mkdir -p /var/log/lighttpd chown www-data.www-data /var/log/lighttpd ...
- Die wohl bessere Lösung: Man nutzt fuer / ein Overlay Dateisystem. Dabei werden die Änderungen getrennt vom eigentlichen Dateisystem gespeichert, so dass man ein System im Ram für die Änderungen nehmen kann. Gut beschrieben unter https://www.raspberrypi.org/forums/viewtopic.php?t=161416