PHP Sonos (Klasse zum Ansteuern einzelner Player)

Hallo Luca,
sehe keinen Fehler.
Kommt keine Fehlermeldung? Was steht in der .log-Datei?

Gruß, Peter

Moin,
unten unter dem Script bei Textausgabe erschient das Script nochmal so wie oben angegeben, Fehlermeldung keine, im Reiter „Meldungen“ erscheint nichts… Muss ich die PHPSonos.inc.php nur in den Scripts Ordner kopieren oder noch irgenwie einbinden? Nur diese Datei oder noch andere? Muss ich am Sonos vorher noch irgendwas aktivieren? Der Sonos ist über WLan direkt am WLan Router drin…

Gruß

Dann mach es mal so.

<?
include("PHPSonos.inc.php");
$sonos = new PHPSonos("192.168.1.43"); //Sonos ZP IPAdresse
$sonos->SetMute(true);  
?>

Moin,
Tatsache, das wars, keine Ahnung wie das passieren konnte… Hat jemand eine einfache Möglichkeit gefunden die URLs von Webradios auszulesen? Habe hier als Beispiel Jam FM und bekomme es einfach nicht hin. Wireshark liefert nichts brauchbares und auch wenn ich mit über IPS mit GetPositionInfo die Daten in ein Array hole zeigt der ausgelesene Link später in Verbindung mit SetRadio keine Wirkung… Hier mal der ausgelesene „Link“ als Beispiel:

aac://rtlberlin.hoerradar.de/jamfm-aac-64?sABC=54591083%230%23rq2sp76rsor38r6175n98n476913o7q5%23gharva&amsparams=playerid:tunein;skey:1415123075

Gruß

Hallo Luca,

hier die Scripts mit denen ich die Sender aus ‚Meine Radiosender‘ aufliste, auslese und starte.

Kommt alles irgend wie hier aus dem Forum.

Function zur Senderermittlung:

<?
//Listet die Radiosender in "Meine Radiosender" im Sonos

function senderIDermittlung($browselist, $senderName)
{
    //speichere Dir den Sender als Favorit im Sonos Controller (damit ein Bild angezeigt wird, musst Du über den Controller bzw. tunein gehen).
    //Danach kannst Du dir über diesen Code die richtige URl ausgeben lassen
//    $browselist = $sonos->Browse("R:0/0","c");
//    print_r($browselist);

    //anzahl der einträge im array der sender ermitteln
    $anzahl = count($browselist);
//    print_r($anzahl."
");

    //für jeden eintrag im sender-array schauen wie die id des gewünschten senders ist
    for ($i=0; $i<$anzahl; $i++)
    {
        //print_r($browselist[$i]['title'] . "
");
        if (strstr($browselist[$i]['title'], $senderName))
           {$j = $i;
//             echo $j;
             return $j;
            }
    }
}
?>

Script zum ermitteln eines Senders nach Namen (wie er ermittelt wurde), und danach den Start des Senders mit Ramp.

<?
include("PHPSonos.inc.php");
require_once("19281.ips.php"); //sucht die id zum gewünschten sender

$sonos = new PHPSonos($sonos); //Sonos ZP IPAdresse

//speichere Dir den Sender als Favorit im Sonos Controller (damit ein Bild angezeigt wird, musst Du über den Controller bzw. tunein gehen).
//Danach kannst Du dir über diesen Code die richtige URl ausgeben lassen
$browselist = $sonos->Browse("R:0/0","c");
//print_r($browselist);

$senderName = "107.7";

$j = senderIDermittlung($browselist, $senderName);

$sonos->SetRadio(urldecode($browselist[$j]['res']));

$sonos->Play();

/*string $ramp_typeRamp_type --------------------------------------------------
Ramps Volume to $volume using the Method mentioned in $ramp_type as string:
"SLEEP_TIMER_RAMP_TYPE" - mutes and ups Volume per default within 17
seconds to desiredVolume
"ALARM_RAMP_TYPE" -Switches audio off and slowly goes to volume
"AUTOPLAY_RAMP_TYPE" - very fast and smooth; Implemented from Sonos for
the autoplay feature
*/

$sonos->RampToVolume("ALARM_RAMP_TYPE", 15);

?>

Moin,
habe das obere Script (die Function) in ein Script gespeicher und dann das untere Script ebenfalls, dann im unteren Script die IP vom Sonos angepasst und bei $senderName „Jam FM“ eingetragen. Außerdem habe ich bei „require_one“ die Script ID der function, also des oberen Scripts angegeben, richtig so? Jam FM habe ich vorher in der Sonos Software als Favorit gespeichert und abspielen lassen. Führe ich das Script aus geht die Musik aus und in der Textausgabe steht folgendes:

Notice: Undefined index: in C:\IP-Symcon\scripts\14185.ips.php on line 16

Fatal error: Uncaught exception ‚Exception‘ with message 'Error sending command: HTTP/1.1 500 Internal Server Error
CONTENT-LENGTH: 347
CONTENT-TYPE: text/xml; charset=„utf-8“
EXT:
Server: Linux UPnP/1.0 Sonos/27.2-80271 (ZPS1)
Connection: close

s:ClientUPnPError’ in C:\IP-Symcon\scripts\PHPSonos.inc.php:2308
Stack trace:
#0 C:\IP-Symcon\scripts\PHPSonos.inc.php(965): PHPSonos->sendPacket(‚POST /MediaRend…‘)
#1 C:\IP-Symcon\scripts\14185.ips.php(18): PHPSonos->Play()
#2 {main}
thrown in C:\IP-Symcon\scripts\PHPSonos.inc.php on line 2308

Hänge also wieder fest!

Hallo Luca,

die Function liest nicht die Sonos Favoriten, sondern unter Radio „Meine Radiosender“. Dann entfern mal die // vor print_r($browselist); im Script (nicht in der Function).
Dann bekommst Du in einem Array alle Sender aufgelistet. Unter Title steht der Name der ins Script gehört.

Hi,

ich versuche gerade erfolglos, die Wiedergabe von einer Master Sonos auf eine SlaveSonos zu übergeben Manuell mit dem Controller geht das, indem man zuerst eine Gruppe einrichtet und dann den Master daraus entfernt - anschließend ist die Wiedergabe einfach auf die 2.te Sonos weitergegeben. Damit möchte ich einfach die Wiedergaben z.B. vom Schlafzimmer in die Küche verlagern…

Aber mit Addmember und Removemember klappt das nicht:
Füge ich mit Addmember einen Slave hinzu wird zwar die Gruppe eingerichtet, den Master kann ich aber dann mit Removemember nicht mehr entfernen. Nur den Slave kann ich aus der Gruppe wieder entfernen.

Hat jemand eine Idee, wie ich den Master aus der Gruppe entfernen kann?

Hallo Leute,
hab mir hier alles durchgelesen, tolle Arbeit! Hab aber ein Problem mit der Wiedergabe von Playlisten. Verwendet hab ich hier die letzte PHPSonos.inc.php vom 05.02.12. Das abspielen von Radiosendern funktioniert, ebenfalls das befüllen der Queue mit der Playlist, nur wird diese leider nicht abgespielt. :frowning: Vielleicht hat ja jemand eine gute Idee.
Hier mal das verwendete Coding.


$PlaylistName = "Bad";
$sonos->ClearQueue();
foreach ($sonos->GetSONOSPlaylists() as $sonoslist){ 
  if ($sonoslist['title']==$PlaylistName){ 
  $PlaylistID = substr($sonoslist['id'], 3); 
  break; 
  } 
}  

$uuid = "RINCON_000E5831FF8401400"; 
$sonos->AddtoQueue("file:///jffs/settings/savedqueues.rsq#".$PlaylistID); 
$sonos->SetQueue("x-rincon-queue:".$uuid."#0");
$sonos->Play();


Antwort selber gefunden, in der UIID muss natürlich die korrekte Mac eingebunden sein. :slight_smile:

Kennt jemand den Befehl um die Lautstärke einer Gruppe zu ändern?
Wenn ich nur den Coordinator anspreche, ändern sich die Member nicht mit.

Danke, falls jemand was weiß. :slight_smile:

Gruß
dfhome

Auch eine Frage von meiner Seite: Gibt es schon eine funktionierende Lösung für das Trennen des Coordinators aus der Gruppe? Per App kann man ihn ja leicht abwählen und einer der Member wird neuer Coordinator. Über php funktioniert das leider nicht…
Grund ist einfach dass ich oft wechselnde Konstellationen habe und nie sicher wissen kann, wer Coord ist.
Lieben Dank falls dafür jemand eine Lösung weiß!!

Hi,

Zu dem Coordinator: du kannst doch einfach am Slave den Befehl „BecomeCoordinatorOfStandaloneGroup“ absetzen. Dieser bildet dann in Zukunft (nach diesem Aufruf :slight_smile: eine eigene Gruppe. Wenn das die Wiedergabe auf den falschen Wert stellt, kannst du den Befehl auf dem Master versuchen. Ich bin mir da nie so sicher, vermute aber, dass in deinem Fall eher der Aufruf beim Master korrekt ist :slight_smile:
Irgendwo weiter vorne gab es dazu schon mal den kompletten SOAP-Aufruf dazu, ansonsten einfach einen bestehenden Aufruf am Service „AVTransport“ anpassen, der Befehl braucht nur eine „0“ als Wert für den Parameter „InstanceID“.

Zur Gruppenlautstärke: Dafür gibt es extra Befehle. Zunächst musst du einmal „SnapshotGroupVolume“ mit der „InstanceID“ „0“ am Service „GroupRenderingControl“ aufrufen. Damit wird das Lautstärkeverhältnis der Gruppe festgehalten, und für die folgenden Aufrufe von „SetGroupVolume“ mit den Parametern „InstanceID“ (wieder die „0“) und „DesiredVolume“ (die gewünschte Gruppenlautstärke) verwendet.
Analog dazu gibt es auch noch „SetGroupMute“ mit den Parametern „InstanceID“ und „DesiredMute“, sowie dazu passende Getter mit „GetGroupVolume“ und „GetGroupMute“.

Grüße
Reiner

Hallo Reiner!

Herzlichen Dank für deine Information! Das hat mir bei einem sehr alten Problem wirklich geholfen. Perfekt.
:smiley:

Eines der wenigen Probleme die bis zur perfekten Sonos Integration in IPS übrig bleiben, ist die Möglichkeit, auch auf den Spotify Account zugreifen zu können. Mittles FHEM scheint das auch schon gelöst worden zu sein…
gibt es da auch schon Ansätze via IPS? Ich habe im Forum leider noch nichts gefunden…

Das wäre ja auch sensationell…

Herzlichen Dank für jede Hilfe!

Hallo Pezi737,

ich bin der Autor des Sonos-Moduls in Fhem, und hier nur Gast, da ich das System hier nicht einsetze :slight_smile:

Was meinst du mit „auf den Spotify-Account zugreifen“?
In Fhem habe ich darüber (über die offizielle Spotify Web-API) lediglich das Cover in einer großen Auflösung geladen. Alles andere sind Funktionen, die Sonos selbst beherrscht.
Leider (oder eigentlich besser: Gott sei Dank) kann man kein Zugangstoken oder sonstige Zugangsdaten für Spotify offen bei Sonos auslesen, sodass man mit der API auf offene Informationen beschränkt bleibt.

Den Zugriff zur API kannst du hier nachlesen: Web API Endpoint Reference - Spotify Developer
Dort kannst du auch eine Suche durchführen, und die gefundenen Titel (bzw. deren ID) an Sonos weiterreichen. Allerdings ist die Spotify-Suche sehr Mensch-lastig. Das bedeutet, dass die Ergebnisse nicht immer wirklich gut sind, sondern eher auf Masse ausgelegt sind.

Was genau möchtest du denn machen?

Grüße
Reiner

Hallo Reiner!

Nochmals herzlichen Dank für deine ausführliche Antwort.
Mein Vorhaben ist wahrscheinlich recht banal… ich möchte einfach auf die abgespeicherten Spotify Playlisten zugreifen. Sprich auslesen und in die Queue setzen - und das am besten ohne dass man alle Listen zu den Sonos Favoriten hinzufügen muss. Meine Frau findet das nicht besonders übersichtlich wenn alles in einer Gruppe zusammengefasst ist.:rolleyes:
Ich habe mich also falsch ausgedrückt. Ich will nicht auf Spotify, sondern nur auf die gespeicherten Playlisten zugreifen.

Vielen Dank für jede Hilfe,

Peter

Hi Peter,

ok, wenn du nicht über die Sonos-Favoriten gehen möchtest, dann wird es etwas komplizierter und du musst die Playlisten selber bei Spotify auslesen und zum Sonos übertragen.

Die Anfrage bei Spotify muss dann authentifiziert erfolgen. Das bedeutet, dass du in deinen Skripten deine Spotify-Zugangsdaten (bzw. ein dafür erzeugtes Token) hinterlegen musst. Sonst kommst du nicht an deine eigenen Playlisten ran.
Unter dieser Adresse ist der Zugriff auf deine Playlisten beschrieben: Get a Playlist - Spotify Developer
Aber vorher musst du eine Authentifizierung bei Spotify durchführen. Da müsstest du unter Web API Tutorial - Spotify Developer mal nachschauen. Dort wird der Vorgang der Applikationsregistrierung und damit auch Authentifizierung beschrieben.

Damit erhältst du dann eine Liste von Tracks, die jeweils eine ID enthalten. Diese ID kannst du dann verwenden, um einen Titel der aktuellen Sonos-Abspielliste hinzuzufügen.
Dazu brauchst du zusätzlich noch die sid und flags, die Sonos für deinen Spotify-Account verwendet. Das kannst du dir bei der TrackURI raulesen. Bei mir sieht die z.B. so aus:

x-sonos-spotify:spotify:track:7y2YUIyCuVhBidENVT0068?sid=9&flags=32&sn=1

Dabei ist der Teil zwischen „track:“ und „?sid=“ die ID des Titels, den du über die Spotify-Suche ermittelt hast, und der ganze Rest drumherum ist fest für deine Sonos-Installation mit deinem Spotify-Konto…

Dann brauchst du noch beim Hinzufügen von Titeln in die Abspielliste die Metadaten.
Die sind auch einigermaßen konstant. Allerdings gibt es dort einen Konto-Kürzel für dein Spotify-Konto.
Hier ist mal ein Metadatastring mit Pseudo-Code, wie er bei mir gültig ist:


$resOrig = "x-sonos-spotify:spotify:track:7y2YUIyCuVhBidENVT0068?sid=9&flags=32&sn=1";
$resZumEinfuegen = "x-sonos-spotify:" + uri_escape("spotify:track:7y2YUIyCuVhBidENVT0068") + "?sid=9&flags=32&sn=1";
$2 = uri_escape("spotify:track:7y2YUIyCuVhBidENVT0068");
$userID_Spotify = uri_unescape("SA_RINCON2311_X_%23Svc2311-0-Token");

$metadata = "DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="$2" parentID="" restricted="true"><dc:title></dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class><desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">$userID_Spotify</desc></item></DIDL-Lite>"

Natürlich musst du deine von Sonos verwendete Spotify-ID selbst ermitteln :slight_smile:
Den gültigen Rahmen musst du einmal bei dir auslesen und in deinem Skript ablegen…

Ziemlich viel zu tun, aber ich denke, es sollte alles machbar sein…
Bei Fragen, einfach fragen :slight_smile:

Grüße
Reiner

Hallo!

Wow. Vielen Dank für die ausführliche Beschreibung! Wenn ich am We etwas Zeit finde, werde ich das Ganze mal auf Praxistauglichkeit überprüfen.
Ich in gespannt, ob ich das so hinbekomme.

Auf jeden Fall lieben Dank dass du dir die Zeit für eine Antwort genommen hast.

Peter

Hallo Reiner!

Ich habe mir das Ganze jetzt in Ruhe angeschaut und bin einigermaßen hoffnungsvoll, dass ich das hin bekomme. :smiley:
Evtl. sogar in die PHPSonos.inc eingebaut.
Nur eine Frage bleibt: Woher bekomme ich am besten meine SpotifyID?
Also den „SA_RINCON2311_X_%23Svc2311-0-Token“ Teil??

Bezieht sich das wiederum auf meinen API Account den ich registriert habe? Sorry, den Teil habe ich noch nicht kapiert.
Herzlichen Dank nochmal für deine Hilfe!!

Peter

Hallo Peter,

das ist doch schon mal gut, dass du da reinkommst. Das ist ja auch viel und komplex auf den ersten Blick :slight_smile:

Diese Spotify-ID bekommst du am Besten mit einem UPnP-Tool wie dem „Intel Device Spy“ heraus. Mit diesem kannst du dich für Titeländerungen am Device registrieren lassen.
Dann die aktuelle Abspielliste leermachen.
Zum Schluss einen beliebigen Titel aus dem Spotify-Bereich (aber nicht aus einer Playliste, sondern z.B. aus den Top-Charts) abspielen lassen.

Dann erhältst du ein Transport-Event. Dort in den XML-Daten gibt es einen Tag „EnqueuedTransportURIMetaData“. Dort steht zwischen den Tags „<desc>“ diese ID.

Natürlich bekommst du die Info auch, wenn du sowie schon eine Transport-Subscription in deinem Skript haben solltest.
Mein Beispiel dieser ID war übrigens Encoded. Im Original gibt es bei mir dort drin ein Hash-Zeichen (#), welches bei Fhem beim Speichern für Probleme sorgt, und dementsprechend von mir kodiert wurde…

Das Ding ist irgendein interner Sonos-Schlüssel für Spotify. Das bleibt vermutlich konstant pro Anwender, ich weiss aber nicht, ob du einfach meine verwenden könntest. Ich habe bisher nur meine gesehen :slight_smile:
Das hat also nix mit deinem Registrierungsschlüssel zu tun, den du dir für diese Playlist-Suche für die Spotify-API erzeugen musst…

Grüße
Reiner