Heute stelle ich euch mal die Integration von Sonos in meine FHEM Haussteuerung vor. Aktuell verfüge ich über zwei Sonos Play:3, eine Play:1 sowie eine Sonos Connect. Der Umfang der Funktionen des SONOS Modul ist mittlerweile recht groß. Allerdings nutze ich aktuell nur die Basisfunktionalitäten. So sind die Sonosplayer in Bad und Küche in die Weckfunktion integriert. Insbesondere als Erinnerung für das Herausstellen der Mülleimer wird die Möglichkeit der Sprachausgabe über die Sonos Player genutzt.
Weiterhin bin ich im Moment damit beschäftigt, diverse Informationen für die Sprachausgabe vorzubereiten. So soll u.a. mittels der Flic-Button die Möglichkeit geschaffen werden, dass man sich morgens im Bad über die aktuelle Verkehrslage oder das Wetter informieren kann.
Nachfolgend werde ich kurz die eigentliche Installation des Sonos Modul auf einem Raspberry Pi darstellen und dann meine Einbindung in die Tablet Oberfläche erläutern.
Vorbereitung auf Linux Ebene
Damit das Sonos-Modul funktioniert, müssen vor der Definition in FHEM auf Linux-Ebene einige Perl-Module installiert werden. Für ein Raspberry kann dies mit folgenden Befehlen durchgeführt werden:
sudo apt-get install libwww-perl sudo apt-get install libsoap-lite-perl sudo apt-get install libxml-parser-lite-perl
Sonos Modul in FHEM installieren
Die Installation einer Sonos Umgebung innerhalb FHEM ist relativ simpel. Idealerweise sollte man bestehende Gruppen vorab innerhalb der Sonos Umgebung auflösen, damit alle Player richtig erkannt werden. Definiert wird quasi ein „Zentralgerät“. Die einzelnen Player sollten dann eigentlich selbst erkannt werden. Zusätzlich werden noch einige ReadingsGroup automatisch erstellt, so dass man die Player direkt über die FHEM Oberfläche steuern kann.
Sonos stellt regelmäßig neue Versionen seiner Betriebssoftware bereit, die man idealerweise zeitnah installieren sollte. Auch das Sonos-Modul in FHEM sollte mit einem regelmäßigen Update-Befehl auf den neuesten Stand gebracht werden. Einige Problemstellungen sind oft auf die unterschiedlichen Versionen von Sonos Firmware und FHEM Modul zurück zu führen.
Die Definition von Sonos erfolgt nun mit folgenden Befehl:
define Sonos SONOS localhost:4711 30
Mit dem Befehl habe ich den Port vorgegeben und die Zeit für einen „Alive-Check“ auf 30 Sekunden gesetzt. Im Prinzip sollte die Definition auch ohne diese Angaben mit „define Sonso SONOS“ funktionieren. In diesem Fall wird automatisch der Port 4711 genutzt und die Alive-Zeit auf 10 Sekunden gesetzt.
Nach kurzer Zeit sollten nun alle Player – die hoffentlich auch Online sind – erkannt und innerhalb FHEM automatisch angelegt werden. Zur Sicherheit kann ein „save“ nicht schaden.
Die Sonos-Module sind sehr gesprächig, so dass die Log-Files gerne recht umfangreich befüllt werden. Wer das nicht möchte, sollte das Attribut „verbose“ auf einen Wert kleiner 3 setzen (3 ist der Default-Wert). Ich habe den Wert bei mir mittlerweile auf 0 gesetzt.
Über die automatisch angelegten Fernbedienungen in FHEM sollte man nun seine Player bedienen können.
Sonos in die Tablet UI Oberfläche integrieren
In meiner Umgebung habe ich u.a. eine eigene Seite für alle vorhandenen Sonos-Player spendiert. Hier wird das Album-Cover bzw. mein einzig verwendeter Radio-Sender angezeigt und als Bedienung habe ich mir hier auf das Abspielen, Pausieren und die Lautstärke begnügt. Zusätzlich habe ich eine Listbox eingebaut, in der meine Sonos-Playlisten sowie der Radiosender ausgewählt werden können.
Der Code für den Sonos Play:3 in der Küche sieht wie folgt aus:
<li data-row="1" data-col="7" data-sizex="4" data-sizey="2"> <header>Sonos Küche</header> <div class="container left" style="max-width:16em;"> <div data-type="image" data-device="Sonos_Kueche" data-get="currentAlbumArtURL" data-size="40%"></div> <div data-type="label" data-device="Sonos_Kueche" data-get="infoSummarize2"></div> <div data-type="select" data-device="duSonosPlaylists" data-list="Playlist" data-set="Sonos_Kueche" class="wider"></div> </div> <div class="container inline"> <div class="left"> <div data-type="push" data-device="Sonos_Kueche" data-set-on="PLAY" data-icon="fa-play" class="cell bigger"></div> <div data-type="push" data-device="Sonos_Kueche" data-set-on="PAUSE" data-icon="fa-pause" class="cell bigger"></div> </div> <div class="right"> <div data-type="volume" data-device="Sonos_Kueche" data-get="Volume" data-set="Volume" data-min="0" data-max="30"></div> <div data-type="label" data-device="Sonos_Kueche" data-get="transportState"></div> </div> </div> <div> </li>
Playlist für Anzeige im TabUI vorbereiten
Bis auf die „Playlist“ für die Nutzung in der Listbox werden die verfügbaren Eigenschaften der Sonosplayer genutzt. Für die Playlist verwende ich ein Dummy-Device innerhalb FHEM, welches einfach mit „define duSonosPlaylists DUMMY“ angelegt wird. Dieses Device wird einerseits dazu genutzt, die Playlisten so bereit zu stellen, dass sie im TabUI mit einem „Select“ Widget dargestellt werden können. Darüber hinaus wird aber das Abspielen einer ausgewählten Liste gestartet. Dies geschieht mit dem folgenden notify.
define notSonosPlaylistAbspielen notify duSonosPlaylists {SonosPlaylistStarten($EVENT)}
Die Funktionen zum Abspielen einer ausgewählten Playlist und zum Befüllen des Dummy mit allen Sonos Playlisten erfolgt mit zwei Funktionen, die in der 99_myutils.pm angelegt werden.
# # aktuelle Sonos Playlists ermitteln und im Dummy als Liste speichern # evtl. noch einen regelmäßigen Trigger erstellen, aktuell nur bei manuellem Aufruf # sub MeinePlayList() { #Buero ist am Rooter und immer an, daher Playlist hier ermitteln #manchmal dauert es etwas länger, die Playlisten zu ermitteln. Hier müsste man eigentlich noch ein "sleep" einfügen #bisher nur durch manuellen Neuaufruf realisiert fhem("get Sonos_Buero Playlists;"); my $Playlist = ReadingsVal("Sonos_Buero", "LastActionResult", "Keine"); my @Playlists = split('GetPlaylists: ', $Playlist); #zusätzllich noch unseren einzigen Radiosender dazu packen my $playlistneu = 'SWR3 Elchradio,'.$Playlists[1]; #playlist für TABUI select aufbereiten $playlistneu =~ s/,/:/g; $playlistneu =~ s/\"//g; fhem("setreading duSonosPlaylists Playlist ".$playlistneu); } # # Bei Aufruf aus TabUI die ausgewählte Sonos Playlist auf dem gewünschten Gerät starten # sub SonosPlaylistStarten($) { my ($Playlist) = @_; my @player = split(' ',$Playlist); my @Liste = split($player[0]." ", $Playlist); $Liste[1] =~ s/ /%20/g; # falls der Radiosender gewählt wurde if($Playlist =~ /SWR3/) { fhem("set $player[0] StartRadio $Liste[1]"); } else { fhem("set $player[0] StartPlaylist $Liste[1]"); } }
Wie in den Kommentaren der Funktion aufgeführt, rufe ich die Funktion „MeinePlayList()“ nur von Hand auf, da sich meine Playlisten nicht sehr häufig ändern. Mit einem at-Befehl könnte man die Playlist natürlich regelmäßig neu befüllen, damit sie auch wirklich aktuell ist.
Sprachausgabe mittels Sonos
Zum Schluß möchte ich noch kurz auf die Sprachausgabe mittels Sonos eingehen. Hierzu gilt es wieder einige Vorbereitungen auch auf dem Raspberry selbst durchzuführen. Benötigt wird ein Verzeichnis in dem die Sprachdateien abgespeichert werden können. Wichtig hierbei ist es, auf die richtigen Rechte zu achten.
Zunächst muß ein Samba-Daemon ausgeführt werden, der dafür sorgt, dass Verzeichnisse innerhalb Windows sichtbar gemacht werden können. Die Installation der entsprechenden Module erfolgt auf dem Raspberry mit folgendem Befehl:
sudo apt-get install samba samba-common-bin
Nun muß das Verzeichnis für die Sprach-Dateien angelegt werden:
sudo mkdir /mnt/SonosSpeak
Nun muß noch in der Samba Konfigurationsdatei eine Änderung übernommen werden. Das kann zum Beispiel mit dem Editor „nano“ erfolgen.
sudo nano /etc/samba/smb.conf
In dieser Datei sollte man auch prüfen, ob in der Sektion Global ([global]) „security = share“ steht oder nicht definiert ist. Nun trägt man am besten am Ende der Datei eine neue Sektion für Sonos wie folgt ein:
[SonosSpeak] comment = Audio-Files for SonosPlayer to Speak read only = false path = /mnt/SonosSpeak guest ok = yes
Jetzt wird der Samba Server gestartet und anschließend sollte man unter Windows auf das Verzeichnis „SonosSpeak“ zugreifen können.
sudo /etc/init.d/samba restart
Nach diesen Vorarbeiten müssen wir jetzt nur noch im Sonos Device die entsprechenden Informationen hinterlegen. Dies geschieht mittels der Attribute „targetSpeakDir“ (Verweis auf den Ordner) und „targetSpeakURL“. Bei diesem Attribut handelt es sich um die URL, die von den Playern genutzt werden kann, um auf die erzeugten Sprachdateien zuzugreifen. In unserem Beispiel müssen die Werte also wie folgt gesetzt werden:
targetSpeakDir /mnt/SonosSpeak targetSpeakURL \\192.168.2.47\SonosSpeak
Bei der IP Adresse handelt es sich um die IP unter der der Raspberry verfügbar ist. Damit es keine Probleme gibt, sollte man den Router am besten so einstellen, dass dieser immer die gleiche IP bekommt oder evtl. statt dessen einen Namen verwenden.
Jetzt können wir endlich testen, ob die Sprachausgabe funktioniert. Hierzu kann folgender Befehl in die FHEM Befehlsbox eingegeben werden:
set Sonos_Kueche Speak 45 de Hallo hier spricht dein Sonos Player
Die Sprachausgabe wird dann mit einer Lautstärke von „45“ auf dem ausgewählten Player ausgegeben.
Weitere umfangreiche Erklärungen sind auch im FHEM-Wiki zu finden.
Ich hoffe, dass euch dieses kleine Beispiel zeigt, wie man seine Sonos Landschaft in FHEM integriert und mittels TabletUI bedienen kann. Auf Grund der umfangreichen Funktionen lassen sich natürlich noch viele andere Steuerungsmöglichkeiten einbauen. Ich habe zum Beispiel die Sonos Geräte im Bad und in der Küche in meine Weckfunktion integriert. So werde ich morgens mit „SWR3“ geweckt und nach 90 Minuten schalten sich die Player spätestens aus, wenn dies nicht bereits durch die Abwesenheitsfunktion erledigt wurde. Damit brauche ich mich nicht um die Player kümmern. Falls tagsüber einmal mit einer höheren Lautstärke Musik gehört wurde, habe ich neulich noch eine Funktion integriert, die vor dem Wecken die Lautstärke auf einen Default-Wert zurück setzt.
Schöner Artikel, vielen Dank dafür.
Aber wie rufst du die Funktion MeinePlayList() von Hand auf?
Man kann Funktionen mittels geschweifter Klammern über das FHEM-Befehlsfeld aufrufen. Also {Funktion()}.
Danke Jürgen 🙂
Hallo Jürgen,
ich habe mich mal an nur einem Button für Play und Pause versucht:
Es wird immer angezeigt welche Aktion man als nächstes ausführen könnte.
Hi Jürgen,
Super Beschreibung hat mir sehe geholfen. Aber eine Frage, wenn ich die Sonos Favoriten Liste abrufen will anstatt die Playlists, was muss ich dann in der 99_myutils.pm ändern?
Danke,
Gruß Markus
Eigentlich muß man den Code nur an zwei Stellen leicht anpassen. Statt „get Sonos_Bueroe playlists“ muss es heißen „get Sonos_Buero favourites“ und ein paar Zeilen weiter in der Funktion muß es heißen „my @Playlists = split(‚GetFavourites: ‚, $Playlist);“ statt „.. GetPlaylists“. Das müsste es eigentlich schon sein. Ach ja und beim Start der Liste müsste es natürlich „StartFavourite“ heißen.
Hallo Jürgen,
genau von dem bin ich eigentlich auch ausgegangen, aber leider habe ich, wenn ich alles in Favourites ändere, nur noch das Radio zur Auswahl. Hier mal mein Code, siehst du einen Fehler?
#
# aktuelle Sonos Playlists ermitteln und im Dummy als Liste speichern
# evtl. noch einen regelmäßigen Trigger erstellen, aktuell nur bei manuellem Aufruf
#
sub
MeinePlayList()
{
#Ankleidezimmer ist am Rooter und immer an, daher Playlist hier ermitteln
#manchmal dauert es etwas länger, die Playlisten zu ermitteln. Hier müsste man eigentlich noch ein „sleep“ einfügen
#bisher nur durch manuellen Neuaufruf realisiert
fhem(„get Sonos_Ankleidezimmer Favourites;“);
my $Playlist = ReadingsVal(„Sonos_Ankleidezimmer“, „LastActionResult“, „Keine“);
my @Playlists = split(‚GetFavourites: ‚, $Playlist);
#zusätzllich noch unseren einzigen Radiosender dazu packen
my $playlistneu = ‚SWR3 Elchradio,‘.$Playlists[1];
#playlist für TABUI select aufbereiten
$playlistneu =~ s/,/:/g;
$playlistneu =~ s/\“//g;
fhem(„setreading duSonosPlaylists Playlist „.$playlistneu);
}
#
# Bei Aufruf aus TabUI die ausgewählte Sonos Playlist auf dem gewünschten Gerät starten
#
sub SonosPlaylistStarten($)
{
my ($Playlist) = @_;
my @player = split(‚ ‚,$Playlist);
my @Liste = split($player[0].“ „, $Playlist);
$Liste[1] =~ s/ /%20/g;
# falls der Radiosender gewählt wurde
if($Playlist =~ /SWR3/)
{
fhem(„set $player[0] StartRadio $Liste[1]“);
}
else
{
fhem(„set $player[0] StartFavourite $Liste[1]“);
}
}
Danke, gruß
Markus
Sieht aus meiner Sicht erst einmal in Ordnung aus. Was zeigt den der SonosPlayer im FHEM an, wenn der Befehl „get Sonos_Ankleidezimmer Favourites“ ausgeführt wurde? Ansonsten würde ich mal ein paar Logs einbauen, um die Variablen in der Funktion zu überprüfen. Z.B. Log3 undef, 3, „Ergebnis Favoriten:“.$Playlist
Sehr komisch, aber ich habe heute Abend nochmal {MeinePlayList()} ausgeführt. Und plötzlich hat es geklappt…. Also alle richtig gewesen.
Viel Dank.
Hallo. Habe heute nach deiner Anleitung den Sonos versucht zu integrieren. Klappt auch alles soweit, nur bei der Sprachausgabe tut sich nichts. Kann in Windows den Ordner lesen aber nichts erstellen. Wie muss ich denn die Rechte anpassen? Bin absoluter Neuling. Bitte nicht zu kompliziert beschreiben 🙂 im eventmonitor bekomme ich außerdem folgenden Eintrag:
Danke
Habs gefunden. Trotzdem danke für die super Anleitung
Freut mich, dass du den Fehler selbst gefunden hast, da ich noch nicht dazu gekommen war, mir die Sache näher anzuschauen.
Hallo Jürgen,
die Anleitung ist top. Jedoch habe ich es noch nicht geschafft, dass die Befehle (Auswahl eines Favoriten Sender) die über FTUI gesendet werden auch in FHEM ankommen.
Ich weiß nicht genau wo der Fehler liegt, aber vielleicht daran
„aktuelle Sonos Playlists ermitteln und im Dummy als Liste speichern“
Vielen Dank für deine Hilfe.
Gruß
Daniel
Hat sich erledigt, ich hatte ein Leerzeichen zwischen StartFavourite 🙁
fhem(„set $player[0] Start Favourite $Liste[1]“);
Daaaanke!!!
Hallo Jürgen,
ich habe das Ganze so aufgesetzt wie in deiner Anleitung, aber manche Sachen funktionieren noch nicht und zwar die Buttons funktionieren, aber die Liste meiner Favoriten bekomme ich nicht in die Combobox. Wenn ich {MeinePlaylist()} ausführe, dann bekomme ich im log folgenden Fehlereintrag:
2017.09.09 14:23:38 1: PERL WARNING: Use of uninitialized value $Playlists[1] in concatenation (.) or string at ./FHEM/99_myUtils.pm line 76.
2017.09.09 14:23:38 3: set Playlist: StartRadio Radio-RockAntenne::Favoriten : Please define Playlist: first
2017.09.09 14:23:38 3: set DM_Playlist: PLAY : Please define DM_Playlist: first
2017.09.09 14:23:38 3: setreading DM_Playlist: default Radio-RockAntenne::Favoriten : Please define DM_Playlist: first
2017.09.09 14:23:38 3: N_SonosPlaylistAbspielen return value: Please define DM_Playlist: first
2017.09.09 14:23:38 3: set DM_default: PLAY : Please define DM_default: first
2017.09.09 14:23:38 3: setreading DM_default: default Favoriten : Please define DM_default: first
2017.09.09 14:23:38 3: N_SonosPlaylistAbspielen return value: Please define DM_default: first
Kannst du mir sagen was ich falsch mache?
Danke und lG
Walter
Auf Anhieb kann ich nicht erkennen, wo das Problem liegt. Aber ich würde mal annehmen, dass irgend etwas bei der Definition der Funktion nicht in Ordnung ist. Irgend ein Klammer-Problem vielleicht.
Hallo,
sodala, habe scheinbar das Problem gelöst und zwar habe ich recht veraltete SONOS-Module im Einsatz gehabt. Ich habe ein update vom gesamten FHEM samt Module durchgeführt und siehe da… es hat zwar funktioniert, jedoch ist FHEM alle paar Stunden ausgefallen und mein BananaPi musste resetiert werden. Nach langem Suchen habe ich dann im FHEM-Forum gelesen, dass die neueste Version vom SONOS-Modul noch einige Bugs hat und ich habe dann folgende Module downgegraded:
00_SONOS.pm 13952 2017-04-09
21_SONOSPLAYER.pm 13898 2017-04-04
ControlPoint.pm 13971 2017-04-11
Jetzt scheint es gut zu funktionieren!
danke nochmals für die Hilfe!
lG
Walter