Wie ich das Thema Multiroom-Audio bei mir umgesetzt habe, habe ich ja hier schon erklärt. In diesem Beitrag möchte ich Euch nun zeigen, wie ich meine WLAN-Lautsprecher selber gebaut habe. Im Grunde ist da auch nicht viel dabei: Wir nutzen idealerweise einen Lautsprecher, den wir noch irgendwo herumfliegen haben und bauen da zwei Netzteile, einen Raspberry Pi, Verstärker und noch ein paar Kleinigkeiten ein. Dann haben wir das Gröbste geschafft.

Im Ergebnis erhalten wir dann einen aktiven WLAN-Lautsprecher, der sich per Logitech Media Server und den zugehörigen Apps ansteuern lässt, ein AirPlay-Empfänger für Apple-Geräte und ein DLNA-Renderer für andere Geräte liefert. Außerdem können die Grundfunktionen mit einer IR-Fernbedienung gesteuert werden. Um Stromkosten zu sparen, wird der Verstärker abgeschaltet, wenn er nicht benötigt wird.

Hardware

Material für einen WLAN-Lautsprecher

Beginnen wir mit dem benötigten Material. Das Ganze ist lediglich als Vorschlag zu verstehen und kann nach belieben angepasst werden. Ich habe viel Wert auf die Balance zwischen Preis und Leistung gelegt, immerhin soll der WLAN-Lautsprecher ja auch bezahlbar bleiben. Insbesondere das Kleinmaterial findet sich bestimmt in der ein oder anderen Schublade bei Euch zuhause.

Verstärker

Als ich den ersten WLAN-Lautsprecher gebaut habe, habe ich als Verstärker gleich mehrere TDA7498 100W Stereo Power Amp von Sure Electronics bestellt. Dieses Angebot gibt es jedoch nicht mehr, dafür jede Menge gute Alternativen. Zur Auswahl eines passenden Verstärkers folgende Tipps:

Die Angegebenen Leistungen sind in der Regel Spitzenleistungen, die nur bei extremen Spitzen und Lautsprechern mit 4Ω Impedanz erreicht werden.

Die tatsächliche Leistung ist auch von der Höhe der Spannung abhängig, mit der der Verstärker betrieben wird. Oft sind Bereiche von 9…30V DC, oder 14…36V DC angegeben. Je höher die Spannung, desto höher die Leistung.

Hilfreich ist immer ein Blick ins Datenblatt. Da sind meist Diagramme drin, mit denen man den optimalen Arbeitspunkt bestimmen kann.

Der Arbeitspunkt sollte so gewählt werden, dass die Verzerrung (THD) nicht zu hoch ist.

Mit der Spannungsversorgung wird der Arbeitspunkt dann festgelegt. Für meinen Verstärker und meine Ansprüche sind 28V optimal.

Netzteile, die 28V liefern, gibt es kaum. Man kann jedoch die Ausgangsspannung vieler 24V-Netzteile einstellen. Bei meinem ist die Obergrenze 27,6V. Die habe ich auch eingestellt.

Nach nunmehr über einem Jahr kann ich sagen, dass ich mit den Verstärkern von Sure Electronics sehr zufrieden bin. Es gab bisher keinerlei Ausfälle, Überhitzungen oder sonstige Probleme an meinen WLAN-Lautsprechern. Den Lüfter, der auf dem Kühlkörper montiert ist, hab ich übrigens abgeklemmt. Zum einen ist der recht laut und erzielt innerhalb eines geschlossenen Gehäuses kaum einen Effekt. Zum anderen wird der Verstärker auch nicht übermäßig warm, sodass ich darauf verzichten kann.

Alternatives Material

Ich habe schon verschiedene Komponenten verbaut und manchmal musste ich recht lange nach einer passenden oder preisgünstigen Lösung suchen. Deshalb nachfolgend noch 4 Dinge, die ich im ersten WLAN-Lautsprecher verbaut hatte. Damals noch mit einem Raspberry Pi Modell A. Vielleicht könnt Ihr ja etwas davon gebrauchen.

Lautsprecher zerlegen

Fangen wir also an. Wenn das Material beschafft ist, zerlegen wir den Lautsprecher in sämtliche Einzelteile. Ich habe zudem das Anschlussterminal komplett zerlegt. Darin sollen später Stromanschluss und WLAN-Antenne montiert werden.

Danach muss man einen Weg finden, wie man die ganzen Einzelteile am besten im Gehäuse unterbringt. Das kann relativ langwierig sein, wenn wenig Platz vorherrscht. Alle Teile müssen so gedreht werden, dass man sie nachher auch noch anschließen kann. Ganz wichtig dabei: man sollte in der Lage sein, die SD-Karte vom Raspberry Pi auszutauschen, ohne alles komplett zerlegen zu müssen.

Bei den von mir verwendeten Teilen ist folgende Anordnung sinnvoll (Gehäuse liegt wie oben abgebildet):

Rückwand: Netzteile (links oben und links unten)

Linke Seitenwand: Raspberry Pi + PHAT DAC

Rechte Seitenwand: Frequenzweiche

Unten: Verstärker und Relais-Modul

Einzelteile vorbereiten

Audiokabel löten

Das Audiokabel stellt die Verbindung zwischen der Soundkarte und dem Verstärker her. Wir nehmen zwei Drähte und löten sie zuerst am Chinch-Stecker an. Der Draht des inneren Kontaktes wird dann mit dem innern Kontakt des Klinkensteckers verbunden. Anschließend werden die beiden äußeren miteinander verbunden. Am Klinkenstecker bleibt der Kontakt, der zwischen dem inneren und dem äußeren liegt, frei, da es sich bei diesem WLAN-Lautsprecher um ein reines Mono-Gerät handelt. Sonst müsste man ein Y-Kabel bauen (oder kaufen). Nicht vergessen, die Gehäuse der Stecker über die Drähte zu schieben, bevor der zweite Stecker angelötet wird.

Anschlussterminal

Im Anschlussterminal werden die C8-Buchse für den Stromanschluss, sowie das Antennenkabel montiert. Mit einer RJ45-Kupplung kann man den Lautsprecher auch perfekt für ein Netzwerkkabel vorbereiten. Die Umrisse habe ich auf der Rückseite angezeichnet, mit einem Bohrer in die Ecken gebohrt und den Rest mit Nadelfeilen weggefeilt.

Wer auf eine richtige Werkstatt verzichten muss und stattdessen alles nur am heimischen Schreibtisch machen kann, dem empfehle ich diesen Mini-Schraubstock.

Frequenzweiche löten

Um Platz im Gehäuse zu schaffen, wird die Frequenzweiche an einer neuen Stelle montiert. Die angelöteten Kabel sind dafür leider etwas zu kurz, daher habe ich die alten Drähte entfernt und neue angelötet. Weiß ist hier die Masse, die farbigen Drähte jeweils das Signal. Braun = Audiosignal vom Verstärker, Grau = Signal zum Tieftöner, Orange = Signal zum Hochtöner.

Micro-USB-Kabel

Die Seite mit dem normalen USB-Stecker wird abgeschnitten (benötigen wir auch nicht mehr). Vom verbleibenden Kabelende (das mit dem Micro-USB-Stecker) entfernen wir ein Stück von der Ummantelung und schneiden den Schirm, den weißen und den gelben Draht ab. Vom roten und schwarzen Draht wird etwas Isolierung entfernt und Aderendhülsen aufgepresst.

Sonstiges

Die zwei Stiftleisten werden jeweils auf den Raspberry Pi Zero, sowie den PHAT DAC gelötet. Die zweipolige Anschlussklemme ist für den Verstärker gedacht, der für die Spannungsversorgung nur einen Hohlstecker besitzt. Direkt daneben befinden sich jedoch die Lötpunkte für ein Schraubterminal.

Komponenten einbauen und verkabeln

Wenn die Vorbereitungen abgeschlossen sind, machen wir uns an den Einbau und die Verdrahtung der Komponenten. Wie zu erkennen ist, habe ich die Soundkarte nicht huckepack auf den Raspberry Pi gesetzt, sondern daneben gesetzt beide mit Drähten verbunden. Dies schien mir angesichts dessen, dass noch weitere Komponenten an die GPIO angeschlossen werden müssen, die einfachste Lösung.

Es gilt nun, alle Komponenten im Lautsprechergehäuse einzubauen. Je nach Größe des Gehäuses kann einen das schon zur Verzweiflung bringen. Daher noch ein paar Tipps, wie es etwas einfacher geht:

Drähte einseitig anschließen und das jeweils andere Ende frei hängen lassen, bevor man die Komponenten einbaut. So muss man nur das jeweils andere Drahtende innerhalb des Gehäuses anschließen.

Komponenten, die im hinteren Teil des Gehäuses montiert werden sollen, zuerst einbauen.

Teilweise ist es einfacher, wenn man die Löcher ohne die Komponenten erstmal vorbohrt. Das geht auch mit den Schrauben, mit denen die Teile nachher befestigt werden sollen.

Der mechanische Teil unseres WLAN-Lautsprechers ist nun weitestgehend fertig. Kommen wir also zur Software.

Software

Image aufspielen

Im Beitrag Raspberry Pi: meine Standardkonfiguration habe ich die schonmal recht ausführlich erläutert beschrieben, wie ich meine Raspberry Pi einrichte. Da der Schwerpunkt hier jedoch auf einem funktionierenden WLAN-Lautsprecher liegt, beschränken wir uns hier auf das Wesentliche und nutzen die Boardmittel.

Statt des offiziellen Images von der Raspberry Pi-Downloadseite verwenden wir hier eines, das den benötigten Player bereits beinhaltet. Es gibt da verschiedene zur Auswahl, die je nach Geschmack und Anspruch gewisse Vorteile bieten.

piCorePlayer : Basiert auf Tiny Core Linux und ist extrem schlank und schnell, sehr übersichtlich und Komfortabel, läuft selbst auf der schwächsten Hardware und den ältesten Speicherkarten. Einziger Nachteil für mich: keine python-lirc -Bibliothek verfügbar. Somit funktioniert mein Script mit der Fernbedienung leider nicht. Das Image ist nur 78 MB groß.

: Basiert auf Tiny Core Linux und ist extrem schlank und schnell, sehr übersichtlich und Komfortabel, läuft selbst auf der schwächsten Hardware und den ältesten Speicherkarten. Einziger Nachteil für mich: keine -Bibliothek verfügbar. Somit funktioniert mein Script mit der Fernbedienung leider nicht. Das Image ist nur 78 MB groß. Max2Play : Basiert auf Raspbian und liefert entsprecht auch alles mit, was man gewöhnt ist. Für verschiedene Soundkarten gibt es auch optimierte Images. Allerdings ist die „beworbene“ Oberfläche meiner Ansicht nach viel zu unübersichtlich, schlecht erklärt, recht durcheinander und keineswegs etwas für Anfänger, die sich überhaupt nicht auskennen. Außerdem muss selbst für recht einfache Dinge eine Lizenz erworben werden.

Die PHAT DAC Soundkarte besitzt den gleichen Soundchip wie die HiFiBerry DAC/DAC+ Light, deshalb verwende ich das für HifiBerry optimierte Image von Max2Play. Da ich keine der sonst angebotenen Features benötige, komme ich auch ohne Lizenz aus.

Wenn der Download abgeschlossen ist, spielen wir das Image auf.

Netzwerk einrichten

Wer wie ich einen Raspberry Pi Zero benutzt, hat nun erstmal das Problem, dass dieser keinen LAN-Port besitzt und WLAN erst noch konfiguriert werden muss. Dafür gibt es verschieden-einfache Wege:

Falls der WLAN-Stick eine WPS-Taste besitzt, kann die WPS-Funktion von Max2Play genutzt werden. Die SD-Karte in einen normalen Raspberry Pi stecken, diesen per Kabel ins Netzwerk holen, die WLAN-Einstellungen vornehmen, und die Karte dann in den Pi Zero packen. Den Pi Zero zusammen mit einem USB-Hub, sowie WLAN-Stick, Tastatur und/oder Maus an einen Bildschirm anschließen und die Daten direkt einstellen. Google bemühen .

Für mich ist Variante 2 die einfachste, und mit der geht es auch weiter.

Die Einstellungen nehmen wir per Weboberfläche vor. Diese ist in der Regel unter max2play.local zu erreichen. Alternativ findet Ihr die IP-Adresse über den Router. Anschließend navigieren wir zum Menüpunkt „WLAN & LAN“, geben SSID und Passwort des Netzwerkes ein, oder nutzen die Scan-Funktion.

Soundkarte einstellen

In dem von mir verwendeten HifiBerry-Image kann man direkt auf der Startseite den entsprechenden Typen der Soundkarte auswählen.

Im Standardimage wird die Soundkarte unter dem Menüpunkt „Raspberry Einstellungen“ ausgewählt, sofern man eine Lizenz besitzt. Besitzt man diese nicht, kann man unter dem Menüpunkt „Audioplayer“ lediglich zwischen den vorkonfigurierten wählen. Alternativ können Soundkarten per Kommandozeile eingestellt werden. Dafür benötigt man keine Lizenz.

$ sudo nano /boot/config.txt

Am Ende der Datei kann per dtoverlay die Soundkarte eingestellt werden. Bei meiner sähe das so aus:

dtoverlay=hifiberry-dac

Als nächstes geben wir dem WLAN-Lautsprecher einen vernünftigen Namen, mit dem er dann auch im Logitech Media Server angezeigt wird. Dies geschieht im Menü „Einstellungen / Reboot“. Hier können auch Sprache und Zeitzone eingestellt werden.

Beim Benennen des Players wird gleichzeitig auch der Hostname angepasst. Mir persönlich gefällt das nicht so gut, deshalb werde ich diesen später nochmal über die Kommandozeile anpassen.

Dann noch das obligatorische Expandieren des Dateisystems. Die passende Schaltfläche befindet sich auf der gleichen Seite etwas weiter unten.

Erweiterte Konfiguration & LIRC

Passwort & Hostname

Für die Steuerung unseres WLAN-Lautsprechers per Apple Remote (oder einer anderen Fernbedienung) und das Abschalten des Verstärkers, wenn dieser nicht benötigt wird, müssen wir auf der Kommandozeile noch ein paar Einstellungen vornehmen. Dazu verbinden wir uns per SSH und loggen uns mit dem Benutzernamen pi und dem Passwort raspberry ein.

Optional: Bei Bedarf das Passwort ändern:

$ sudo passwd pi

Optional: Um dem Raspberry Pi einen anderen Hostname zu geben, begeben wir uns über die aktive SSH-Verbindung in die Konfigurationsoberfläche…

$ sudo raspi-config

…wählen 9 Advanced Options -> A2 Hostname und tragen hier den neuen Hostname ein. Wir verlassen die Oberfläche und starten neu.

LIRC installieren & konfigurieren

Über das Thema LIRC, und wie man Python-Scripte mittels Fernbedienung steuert, hatte ich hier schon einmal sehr ausführlich geschrieben. Daher machen wir hier einen Schnelldurchlauf. Zuerst installieren wird LIRC:

$ sudo apt-get update

$ sudo apt-get install lirc python-lirc

Nach Abschluss der Installation machen wir uns an die Konfiguration. Als erstes der „Autostart“ von LIRC.

$ sudo nano /etc/modules

Die markierten Zeilen werden einfach unten angehangen.

# /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. # Parameters can be specified after the module name. lirc_dev # GPIO in BCM-Zählweise lirc_rpi gpio_in_pin=23

Auf Zeile 9 geben wir in BCM-Zählweise an, welchen GPIO wir mit LIRC nutzen wollen – also die GPIO-Nummer, nicht die Pin-Nummer. Danach passen wir die Hardware-Konfiguration von LIRC an.

$ sudo nano /etc/lirc/hardware.conf

Hier tragen wir für LIRCD_ARGS , DRIVER , DEVICE und MODULES die Werte wie abgebildet ein.

# /etc/lirc/hardware.conf # # Arguments which will be used when launching lircd LIRCD_ARGS="--uinput" #Don't start lircmd even if there seems to be a good config file #START_LIRCMD=false #Don't start irexec, even if a good config file seems to exist. #START_IREXEC=false #Try to load appropriate kernel modules LOAD_MODULES=true # Run "lircd --driver=help" for a list of supported drivers. DRIVER="default" # usually /dev/lirc0 is the correct setting for systems using udev DEVICE="/dev/lirc0" MODULES="lirc_rpi" # Default configuration files for your hardware if any LIRCD_CONF="" LIRCMD_CONF=""

Zuletzt müssen wir noch einen Eintrag in der Datei /boot/config.txt ergänzen.

$ sudo nano /boot/config.txt

Hier passen wir Zeile 51 wie folgt an:

# Uncomment this to enable the lirc-rpi module dtoverlay=lirc-rpi,gpio_in_pin=23

Tasten-Mapping & Aktionen

Wer eine andere Fernbedienung als die Apple Remote nutzen möchte, startet den Raspberry Pi jetzt neu und macht an dieser Stelle weiter. Alle mit Apple Remote können mein Tasten-Mapping einfach übernehmen.

$ sudo nano /etc/lirc/lircd.conf

Die Datei befüllen wir, je nach verwendetem IR-Empfänger, mit folgendem Inhalt:

TSOP 31238 # Please make this file available to others # by sending it to <lirc@bartelmus.de> # # this config file was automatically generated # using lirc-0.9.0-pre1(default) on Tue Aug 18 19:23:09 2015 # # contributed by # # brand: /home/pi/lircd.conf # model no. of remote control: # devices being controlled by this remote: begin remote name appleremote bits 8 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 9058 4422 one 624 1595 zero 624 497 ptrail 623 repeat 9058 2194 pre_data_bits 16 pre_data 0x77E1 post_data_bits 8 post_data 0x4E gap 107798 toggle_bit_mask 0x0 begin codes KEY_UP 0xD0 KEY_DOWN 0xB0 KEY_LEFT 0x10 KEY_RIGHT 0xE0 KEY_OK 0xBA 0x20 KEY_MENU 0x40 KEY_PLAYPAUSE 0x7A 0x20 end codes end remote

TSOP 4838 # Please make this file available to others # by sending it to <lirc@bartelmus.de> # # this config file was automatically generated # using lirc-0.9.0-pre1(default) on Sun Oct 16 17:40:15 2016 # # contributed by # # brand: /home/pi/lircd.conf # model no. of remote control: # devices being controlled by this remote: begin remote name appleremote bits 8 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 9057 4419 one 600 1616 zero 600 525 ptrail 600 repeat 9058 2190 pre_data_bits 16 pre_data 0x77E1 post_data_bits 8 post_data 0x4E gap 107804 toggle_bit_mask 0x0 begin codes KEY_UP 0xD0 KEY_DOWN 0xB0 KEY_LEFT 0x10 KEY_RIGHT 0xE0 KEY_OK 0xBA 0x20 KEY_MENU 0x40 KEY_PLAYPAUSE 0x7A 0x20 end codes end remote

Damit beim Tastendruck auch etwas passiert, werden Aktionen definiert. In unserem Fall wollen wir lediglich die Information, welche Taste gedrückt wurde, per String an unser Steuer-Script übergeben. Dazu erzeugen wir uns die Datei lircrc …

$ sudo nano /etc/lirc/lircrc

…und packen folgenden Inhalt rein:

# ~/.lircrc # # button: Name der Taster (wie angelernt) # prog: Ziel, wohin die Information übergeben werden soll (Socket oder Programm) # config: Übergebener String # Apple Remote # KEY_UP # KEY_DOWN # KEY_LEFT # KEY_RIGHT # KEY_OK # KEY_MENU # KEY_PLAYPAUSE begin button = KEY_UP prog = appleremote config = KEY_UP end begin button = KEY_DOWN prog = appleremote config = KEY_DOWN end begin button = KEY_LEFT prog = appleremote config = KEY_LEFT end begin button = KEY_RIGHT prog = appleremote config = KEY_RIGHT end begin button = KEY_OK prog = appleremote config = KEY_OK end begin button = KEY_MENU prog = appleremote config = KEY_MENU end begin button = KEY_PLAYPAUSE prog = appleremote config = KEY_PLAYPAUSE end

Damit ist LIRC fertig eingerichtet und der WLAN-Lautsprecher soweit vorbereitet. Sollte es später irgendwelche Probleme mit LIRC geben, findet Ihr in oben genanntem Beitrag auch Möglichkeiten, die Teilschritte einzeln zu testen.

Zum Abschluss starten wir den Raspberry Pi neu.

Steuerscript für den WLAN-Lautsprecher

Damit die Fernbedienung den WLAN-Lautsprecher steuern kann und der Verstärker beim Abspielen von Musik auch eingeschaltet wird, benötigen wir noch ein Script, das mit dem Server kommuniziert und die entsprechenden Informationen besorgt, bzw. weiterleitet. Eins auf diesen Lautsprecher zugeschnittenes findet Ihr unten. Vom Grunde her könnt Ihr das Script auch 1:1 übernehmen.

Wir erzeugen also die Script-Datei…

$ nano ~/squeezebox-control.py

…und packen folgenden Inhalt hinein:

#!/usr/bin/env python #coding: utf-8 #################################################################### # squeezebox-control.py # Script zur Steuerung eines WLAN-Lautsprechers # von Sebastian Köhler - https://indibit.de # # LETZTE ÄNDERUNG: 17.04.2016 #################################################################### import fcntl, socket, struct # für MAC-Adresse import lirc import RPi.GPIO as GPIO import sys import telnetlib import thread import time # ---------------------------------------------------------------------------- # Konfiguration # ---------------------------------------------------------------------------- HOST = "192.168.243.5" # IP-Adresse des LMS PORT = "9090" # CLI-Port des LMS OFF_DELAY = 180 # Verstärker-Abschalt-Verzögerung (in Sekunden) VOL_NORM = 50 # Lautstärke, die nach beim Einschalten eingestellt werden soll # ---------------------------------------------------------------------------- # sonstige Variablen # ---------------------------------------------------------------------------- mac = '' # MAC-Adresse status = '' # Status des Players tn = '' # Telnet-Verbindung lastPlay = 0 # Zeit, wann der Player das letzte Mal gespielt hat # ---------------------------------------------------------------------------- # MAC-Adresse auslesen # ---------------------------------------------------------------------------- def getMAC(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15])) return '%3A'.join(['%02x' % ord(char) for char in info[18:24]]) # ---------------------------------------------------------------------------- # Telnet-Verbindung herstellen # ---------------------------------------------------------------------------- def tn_connect(): global tn try: tn = telnetlib.Telnet(HOST,PORT) player("startup") except: time.sleep(10) # ---------------------------------------------------------------------------- # WLAN-Lautsprecher bei Start initialisieren # ---------------------------------------------------------------------------- def startup(): setGPIO("startup","") tn_connect() # ---------------------------------------------------------------------------- # Fernbedienung/LIRC abfragen # ---------------------------------------------------------------------------- def remote(): while True: try: codeIR = lirc.nextcode() if codeIR != []: if codeIR[0] == 'KEY_UP': player('vol_up') elif codeIR[0] == 'KEY_DOWN': player('vol_down') elif codeIR[0] == 'KEY_LEFT': player('back') elif codeIR[0] == 'KEY_RIGHT': player('next') elif codeIR[0] == 'KEY_OK': pass elif codeIR[0] == 'KEY_MENU': player('playlist') elif codeIR[0] == 'KEY_PLAYPAUSE': if status == "play": player('pause') else: player('play') time.sleep(0.05) except: time.sleep(0.1) # ---------------------------------------------------------------------------- # Befehle senden, Status abfragen # ---------------------------------------------------------------------------- def player(cmd): p0 = "" p1 = "" p2 = "" if cmd == "startup": try: player("stop") #tn.write("subscribe play,pause,stop,playlist\r") tn.write(mac + " mode ?\r") resetVol() except (EOFError, socket.error): tn_connect() else: if cmd == "play": # Wiedergabe p0 = "play" elif cmd == "pause": # Pause p0 = "pause" elif cmd == "stop": # Stop p0 = "stop" elif cmd == "back": # Titel zurück p0 = "playlist" p1 = "index" p2 = "-1" elif cmd == "next": # Titel überspringen p0 = "playlist" p1 = "index" p2 = "%2B1" elif cmd == "vol_up": # Lauter p0 = "mixer" p1 = "volume" p2 = "%2B5" elif cmd == "vol_down": # Leiser p0 = "mixer" p1 = "volume" p2 = "-5" elif cmd == "playlist": # Playlist abspielen p0 = "playlist" p1 = "play" p2 = "smooth_jazz.m3u" else: p0 = "" p1 = "" p2 = "" if p0 != "": try: tn.write(mac + " " + p0 + " " + p1 + " " + p2 + "\r") except (EOFError, socket.error): tn_connect() p0 = "" p1 = "" p2 = "" def getStatus(): while True: global status try: tn.write(mac + " mode ?\r") q = tn.read_until('\r') s = q.split('\r')[0].split(' ') if s: if s[0] == mac: if s[1] == "mode": status = s[2] except (EOFError, socket.error): tn_connect() except KeyboardInterrupt: getOut() time.sleep(0.1) # ---------------------------------------------------------------------------- # Verstärker am WLAN-Lautsprecher ein-/ausschalten # ---------------------------------------------------------------------------- def ampOnOff(): global lastPlay if status == "play": setGPIO("amp","on") lastPlay = time.time() else: if time.time() - lastPlay >= OFF_DELAY: if status == "pause": resetVol() player("stop") setGPIO("amp","off") def setGPIO(channel,state): amp = 22 on = GPIO.LOW off = GPIO.HIGH if channel == "startup": GPIO.output(22, GPIO.HIGH) #GPIO.output(24, GPIO.HIGH) else: if (channel in locals()) and (state in locals()): GPIO.output(locals()[channel], locals()[state]) # ---------------------------------------------------------------------------- # Standard-Lautstärke setzen # ---------------------------------------------------------------------------- def resetVol(): try: tn.write(mac + " mixer volume " + str(VOL_NORM) + " \r") except (EOFError, socket.error): tn_connect() # ---------------------------------------------------------------------------- # Script beenden # ---------------------------------------------------------------------------- def getOut(): GPIO.cleanup() sys.exit(0) # ---------------------------------------------------------------------------- # Hauptprogramm # ---------------------------------------------------------------------------- if __name__ == '__main__': #GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # Zählweise der Pins festlegen GPIO.setup(22, GPIO.OUT) # Pin 22 (GPIO 25) = Verstärker-Relais 1 #GPIO.setup(24, GPIO.OUT) # Pin 24 (GPIO 8) = Verstärker-Relais 2 sockid=lirc.init("appleremote", blocking = False) # Fernbedienung einbinden mac = getMAC('wlan0') startup() thread.start_new_thread(getStatus,()) thread.start_new_thread(remote,()) while True: try: ampOnOff() n = True time.sleep(0.1) except KeyboardInterrupt: getOut()

Auf den Zeilen 23 bis 26, und 133 müsst Ihr die für Euch zutreffenden Daten eintragen.

Zeile 23 ( HOST ): Die IP-Adresse des Computers/NAS ein, auf dem der Logitech Media Server läuft.

): Die IP-Adresse des Computers/NAS ein, auf dem der Logitech Media Server läuft. Zeile 24 ( PORT ): Der Port für die Steuerung per Telnet. Den Findet Ihr so heraus: Im LMS -> Einstellungen -> Erweitert -> Befehlszeilenschnittstelle (CLI) [oben links im Dropdown-Menü auswählen].

): Der Port für die Steuerung per Telnet. Den Findet Ihr so heraus: Im LMS -> Einstellungen -> Erweitert -> Befehlszeilenschnittstelle (CLI) [oben links im Dropdown-Menü auswählen]. Zeile 25 ( OFF_DELAY ): Zeit, die verstreichen muss, bis der Verstärker abgeschaltet wird, wenn die Wiedergabe pausiert wird.

): Zeit, die verstreichen muss, bis der Verstärker abgeschaltet wird, wenn die Wiedergabe pausiert wird. Zeile 26 ( VOL_NORM ): Lautstärke die automatisch eingestellt wird, wenn der Verstärker sich ausschaltet (STOP) oder bei Neustart des Raspberry Pi, bzw. LMS

): Lautstärke die automatisch eingestellt wird, wenn der Verstärker sich ausschaltet (STOP) oder bei Neustart des Raspberry Pi, bzw. LMS Zeile 133: Hier könnt Ihr eine Playlist festlegen, die beim Drücken auf die Menü-Taste an der Apple-Remote abgespielt wird.

Die Tasten auf der Fernbedienung sind in diesem Script wie folgt belegt:

hoch/runter: lauter/leiser

links/rechts: nächster/vorheriger Titel

Mitte: nicht belegt

Menü: spielt voreingestellte Playlist ab

Play/Pause: befindet sich der Player im Ruhezustand, wird das abgespielt, was zuletzt wiedergegeben wurde. Pause pausiert, anschließend Play setzt die Wiedergabe fort

Das Script muss noch ausführbar gemacht werden:

$ chmod +x ~/squeezebox-control.py

Autostart nach Reboot

Damit alles auch nach einem Stromausfall oder Neustart wie gewünscht von alleine läuft, muss das Script noch automatisch gestartet werden. Im Blog von Stephen C. Phillips habe ich eine tolle Möglichkeit gefunden, das Script als Dienst laufen zu lassen.

Dazu legen wir zuerst das Start-/Stopp-Script an…

$ sudo nano /etc/init.d/squeezebox-control

… und befüllen es mit folgendem Inhalt:

#!/bin/sh ### BEGIN INIT INFO # Provides: myservice # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Squeezebox-control # Description: Reads IR input and controls GPIO for switching the AMP ### END INIT INFO # Change the next 3 lines to suit where you install your script and what you want to call it DIR=/home/pi DAEMON=$DIR/squeezebox-control.py DAEMON_NAME=squeezebox-control # Add any command line options for your daemon here DAEMON_OPTS="" # This next line determines what user the script runs as. # Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python. DAEMON_USER=root # The process ID of the script when it runs is stored here: PIDFILE=/var/run/$DAEMON_NAME.pid . /lib/lsb/init-functions do_start () { log_daemon_msg "Starting system $DAEMON_NAME daemon" start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS log_end_msg $? } do_stop () { log_daemon_msg "Stopping system $DAEMON_NAME daemon" start-stop-daemon --stop --pidfile $PIDFILE --retry 10 log_end_msg $? } case "$1" in start|stop) do_${1} ;; restart|reload|force-reload) do_stop do_start ;; status) status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $? ;; *) echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}" exit 1 ;; esac exit 0

Auf den Zeilen 14 und 15 könnt Ihr Pfad und Dateinamen anpassen, falls Ihr die anders gewählt habt, als ich vorgeschlagen habe.

Jetzt muss das Script noch ausführbar gemacht werden…

$ sudo chmod +x /etc/init.d/squeezebox-control

… und dem System bekannt gemacht werden, dass das neue Start-/Stopp-Script existiert und verarbeitet werden soll:

$ sudo update-rc.d squeezebox-control defaults

Das Ganze kann nun wie folgt gesteuert werden:

Status abfragen $ /etc/init.d/squeezebox-control status Script starten $ sudo /etc/init.d/squeezebox-control start Script stoppen $ sudo /etc/init.d/squeezebox-control stop Script neustarten $ sudo /etc/init.d/squeezebox-control restart

Automatischer Neustart

Von Zeit zur Zeit kann es vorkommen, dass nach ein paar Tagen Laufzeit der Lautsprecher nur noch sehr träge oder garnicht mehr reagiert. Das passiert bei mir bei einem Lautsprecher, der von einem Raspberry Pi 1 Modell B gesteuert wird. Offensichtlich gibt es dort ein Problem mit dem wenigen Speicher, den dieses Modell besitzt. Abhilfe schaft es bei mir, das Steuerscript regelmäßig neu zu starten. Dazu legen wir einen passenden Cronjob an, der als root ausgeführt wird (weitere Informationen über Cron hier).

$ sudo crontab -e

Am Ende der Datei fügen wir folgenden Inhalt ein:

0 4 * * * /etc/init.d/squeezebox-control restart

Damit wird jede Nacht 4:00 Uhr das Script neu gestartet und eventuell vollgelaufener Speicher geleert.

Hinweis: Es wird nur das Steuerscript neu gestartet, nicht der gesamte Raspberry Pi.

Nach einem letzten Neustart ist der WLAN-Lautsprecher nun vollständig betriebsbereit. Viel Spaß 😎