PHP Sonos (Klasse zum Ansteuern einzelner Player)

Moin Stocki…lass mich kurz überlegen…nein :smiley: :stuck_out_tongue:

a) Hier bist du im IP SYMCON Forum
b) Du kannst einen eigenen Thread aufmachen und genauer beschreiben, wo genau dein Problem ist, dann hilft dir vlt. jemand, aber einfach hier anmelden und eine Copy & Paste Anleitung fordern > DaumenRunter

Vor allem hast du selbst schon eine mögliche PHP Class mit einer guten Beschreibung verlinkt. Das ist ja schon quasi Copy&Paste. Mit Faulheit kommt man nicht weit und beliebt macht man sich so auch nicht unbedingt :wink:

Trotzdem viel Erfolg!

Grüße,
Chris

Guten Morgen!

In Post #393 wird auf die Befehle „Set/Get Group Volume“ hingewiesen. Leider scheint diese Funktion in meiner PHPSonos gar nicht implementiert zu sein.
Ich habe jetzt schon längere Zeit mit Wireshark verbracht, um eine Idee davon zu bekommen, wie man sowas anpacken könnte - musste mir aber gerade eingestehen, dass ich da wohl keinen Durchblick habe… :rolleyes:
Hat evtl. jemand ein paar Codezeilen für mich, die ich verwenden kann, um die Gruppenvolume zu setzen?

Vielen Dank für jede Hilfe…

Peter;)

Hi Peter!

Hier eine kleine Info, wie das bei Gruppen mit der Lautstärke abläuft:
http://forums.sonos.com/showpost.php?p=208999&postcount=4

Kurz gesagt, einfach die Gruppen-Member alle einzeln auf Lautstärke X setzen, durch eine Funktion mit foreach oder sowas. Oder von jedem einzelnen Member die Lautstärke auslesen und um z.B. 10 erhöhen.

Grüße,
Chris

Hallo Peter,

der Post stammt von mir. Und ja, den Befehl gibt es in der Klasse noch nicht. Ich habe lediglich das Konzept (und die Befehlsnamen-/parameter) beschrieben, da ich die Klasse hier gar nicht verwende.

Ich würde auf die Sonos-eigene Funktionalität für die Gruppenlautstärke zurückgreifen. Das ist im Prinzip nicht kompliziert, du musst dir nur die von mir beschriebenen Befehle in der Klasse umsetzen (oder vielleicht hat es es schon jemand anderes gemacht, und kann es posten). Ich kann hier immer nur ungetesteten Code posten, der leider nicht immer auf Anhieb funktioniert, da ich hier momentan noch nicht mal PHP vorliegen habe…

Kurz nochmal zum Verständnis:
Wenn du im Sonos-Controller bei einer Gruppe auf den Lautstärkebalken tippst, wird „SnapshotGroupVolume“ ausgeführt, womit also die Lautstärkeverhältnisse, wie sie aktuell in der Gruppe vorliegen, gespeichert werden.
Wenn du dann die Gruppenlautstärke veränderst wird „SetGroupVolume“ ausgeführt, welches dann alle Player im gespeicherten Verhältnis zueinander verändert. Natürlich kannst du auch die Lautstärke an einem Player verändern, was zu einer Anpassung der Gruppenlautstärke führt.

Mit „GetGroupVolume“ kannst du dir die aktuell gesetzte Laustärke holen, um ein Gefühl dafür zu bekommen, welche Lautstärke beim Setzen überhaupt sinnvoll ist. Beim Controller passiert das automatisch dadurch, dass der Slider ja an einer bestimmten Stelle steht, und du ihn von dort verschiebst…

Grüße
Reiner

Das optimale Tool um SOAP/UPnP Befehle herauszufinden >> Device Spy

Anleitung:
Quick Start Tutorial: DeviceSpy | Pelco Developer Network (PDN)

Weitere Infos dazu finden sich bei Google. Aber an sich ist das Ding realtiv selbsterklärend und gut zu bedienen :slight_smile:

>> Wie man das in Scripten dann verwenden kann, kann man sich sehr schön bei den Posts von Nall chan abschauen > Fritzbox mit SOAP steuern :wink:

Viel Erfolg! Die Lösung darf dann gerne hier geposted werden :slight_smile:

Grüße,
Chris

Wow! Vielen Dank für die schnellen, hilfreichen Antworten, Reiner und Chris!!!

Mit Hilfe des Programs Device Spy habe ich den ganzen Sachverhalt endlich mal kapiert! :smiley:
Mit bisschen rumprobieren und abkupfern konnte ich das Skript nun auch erfolgreich erweitern:

public function GetGroupMute() 
	{
$header='POST /MediaRenderer/GroupRenderingControl/Control HTTP/1.1
HOST: '.$this->address.':1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:GroupRenderingControl:1#GetGroupMute"
';
$xml='<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><u:GetGroupMute xmlns:u="urn:schemas-upnp-org:service:GroupRenderingControl:1"><InstanceID>0</InstanceID>
</u:GetGroupMute></s:Body></s:Envelope>';
$content=$header . 'Content-Length: '. strlen($xml) .'

'. $xml;

		return (bool)$this->sendPacket($content);
	}
	
	public function SetGroupMute($mute)
	{

		if($mute) { $mute = "1"; } else { $mute = "0"; }

$header='POST /MediaRenderer/GroupRenderingControl/Control HTTP/1.1
HOST: '.$this->address.':1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:GroupRenderingControl:1#SetGroupMute"
';
$xml='<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><u:SetGroupMute xmlns:u="urn:schemas-upnp-org:service:GroupRenderingControl:1"><InstanceID>0</InstanceID><DesiredMute>'.$mute.'</DesiredMute>
</u:GetGroupMute></s:Body></s:Envelope>';
$content=$header . 'Content-Length: '. strlen($xml) .'

'. $xml;

		$this->sendPacket($content);
	}
	
	public function SetGroupVolume($volume)
	{
$header='POST /MediaRenderer/GroupRenderingControl/Control HTTP/1.1
HOST: '.$this->address.':1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:GroupRenderingControl:1#SetGroupVolume"
';
$xml='<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><u:SetGroupVolume xmlns:u="urn:schemas-upnp-org:service:GroupRenderingControl:1"><InstanceID>0</InstanceID><DesiredVolume>'.$volume.'</DesiredVolume>
</u:SetGroupMute></s:Body></s:Envelope>';
$content=$header . 'Content-Length: '. strlen($xml) .'

'. $xml;

		$this->sendPacket($content);
	}

	public function GetGroupVolume()
	{
$header='POST /MediaRenderer/GroupRenderingControl/Control HTTP/1.1
HOST: '.$this->address.':1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:GroupRenderingControl:1#GetGroupVolume"
';
$xml='<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><u:GetGroupVolume xmlns:u="urn:schemas-upnp-org:service:GroupRenderingControl:1"><InstanceID>0</InstanceID>
</u:GetGroupMute></s:Body></s:Envelope>';
$content=$header . 'Content-Length: '. strlen($xml) .'

'. $xml;

		return (int)$this->sendPacket($content);
	}
	
	public function SnapshotGroupVolume()
	{
$header='POST /MediaRenderer/GroupRenderingControl/Control HTTP/1.1
HOST: '.$this->address.':1400
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:GroupRenderingControl:1#SnapshotGroupVolume"
';
$xml='<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><u:SnapshotGroupVolume xmlns:u="urn:schemas-upnp-org:service:GroupRenderingControl:1"><InstanceID>0</InstanceID>
</u:SnapshotGroupVolume></s:Body></s:Envelope>';
$content=$header . 'Content-Length: '. strlen($xml) .'

'. $xml;

		$this->sendPacket($content);
	}

Alle Funktionen haben den von Reiner perfekt beschriebenen Ablauf!

Nochmals vielen Dank für die Hilfe - wieder was gelernt!

Peter

Hallo,

erstmal danke für diese großartige Klasse.

Eine Funktion jedoch habe ich nicht gefunden:

Wie kann ich den Playmode auf „Repeat 1“ also das Wiederholen eines einzigen Titels stellen?
Ich würde gerne z.B folgendes machen:

$sonos->SetVolume($vol/100*70);
[b]$sonos->SetPlayMode("Repeat1");[/b]
$sonos->SetAVTransportURI("x-file-cifs://touch/IP-Symcon$/media/Meldung.wav");

Im Ergebnis soll Meldung.wav unendlich lange wiederholt werden bis ich einen neuen Befehl an an Player schicke.
Hat jemand eine Idee?

Danke.

Guten Morgen!

Eine Erweiterung von PHPSonos kann ich dir leider nicht anbieten, aber 2 Alternativen:

SonosBY (Sonos // Gruppen erstellen, Gruppen auflösen, Text to Speech, …) (auch bei alten IPS Versionen einsetzbar)

Sonos Modul (nur ab IPS 4.0 einsetzbar)

Grüße,
Chris

Hi Stoffel84,

wenn du den Befehl PlayMode bereits hast, brauchst du nur den korrekten String setzen.

Für Repeat alleine lautet er: „REPEAT_ONE“

Zusammen mit Shuffle musst du „SHUFFLE_REPEAT_ONE“ angeben…

Grüße
Reiner

Hallo,

ich setze PHPSonos.inc.php seit langer Zeit erfolgreich ein. Nun habe ich mein Sonos upgedate und die Funktion GetSonosPlaylists schein nicht zu funktionieren.

In diesem Bereich bricht das PHP ab und echo „7=…“ wird nicht mehr angezeigt:

    $returnContent = str_replace(array("&lt;", "&gt;", """, "&", "%3a", "%2f", "%25"), array("&lt;", "&gt;", "\"", "&", ":", "/", "%"), $returnContent);

echo „<br>6=for GetSonosPlaylists<br>“;
$xml = new SimpleXMLElement($returnContent);
//Hier Fehler???

echo „<br>7=for GetSonosPlaylists<br>“;
$liste = array();

Hat jemand dieselben Erfahrungen gemacht/

Viele Grüße

Hallo und willkommen im IPS Forum :slight_smile:

Dieses Thema ist bekannt und wurde auch schon an einigen Stellen „bearbeitet“ :wink: Siehe z.B. im IPSSonos Thread. Dort gibt es eine überarbeite Version der PHPSonos, welche mit Sonos ab Version 6 wieder funktioniert.

Alternativ gibt es verschiedene Projekte, um Sonos zu steuern (SymconSonos (IPS4 Modul), SonosBY (Skript)).

Grüße,
Chris

Hallo Chris,

vielen Dank für die schnelle Reaktion. Ich hatte vorher im Forum gestöbert, aber leider nicht den letzten Stand des Skriptes PHPSonos.inc.php gefunden.

Nun habe ich das Skript von Deinem Link geladen und unter PHPSonos3.inc.php. Es hat 2371 Zeilen und fängt wie folgt an:

<?php
// URL to gen documentation on my (br) system http://192.168.0.5:82/user/PhpDocumentor/

/**

  • PHPSonos.inc.php
  • PHPSonos class originally released as: Sonos PHP Script - Copyright: Michael Maroszek - Version: 1.0, 09.07.2009
  • Wiki: {@link PHPSonos – IP-Symcon PHPSonos IPS-WIKI }

Leider funktioniert nun gar nichts mehr. Ich rufe das Skript wie folgt auf:

$inc=‚PHPSonos3.inc.php‘;
$zone = ‚Bad‘;
$do= $_REQUEST[‚para‘];

include($inc);
$zones = array(‚Bad‘ => ‚192.168.0.20‘,
‚Kueche‘ => ‚192.168.0.20‘,
‚Buero‘ => ‚192.168.0.20‘,);

if(array_key_exists($zone, $zones))
{
$sonos = new PHPSonos($zones[$zone]); //Sonos ZP IPAdresse

switch($do)
{
case ‚SpielPlaylist1‘:
$PlaylistName = „Playlist1“;
foreach ($sonos->GetSONOSPlaylists() as $sonoslist){
if ($sonoslist[‚title‘]==$PlaylistName){
$PlaylistFILE= $sonoslist[‚file‘];
break;
}
}
$sonos->ClearQueue();
$sonos->AddtoQueue("$PlaylistFILE");
$sonos->SetQueue(„x-rincon-queue:RINCON_“.„gelöscht“.„01400#0“);
$sonos->Play();
break;

case 'SpielPlaylist2':

Mit dem „alten“ Skript PHPSonos2.inc.php funktioniert alles für mich Notwendige bis auf die Funktion GetSONOSPlaylists(). Diese Funktion bricht irgendwie ab.

Viele Grüße

Hallo Uwe,
willkommen im IPS-Forum und viel Spass.

Mal einen kleinen Hinweis: Wenn du PHP-Code im Beitrag schreibst, setze den doch in die PHP-Tags.
Das ist dann besser lesbar.

Dein Code aus dem vorigen Beitrag sieht dann so aus:


$inc='PHPSonos3.inc.php';
$zone = 'Bad';
$do= $_REQUEST['para'];

include($inc);
$zones = array('Bad'    => '192.168.0.20',
               'Kueche' => '192.168.0.20',
               'Buero'  => '192.168.0.20',);
               
if(array_key_exists($zone, $zones))
{ 
  $sonos = new PHPSonos($zones[$zone]); //Sonos ZP IPAdresse
  
  switch($do)
  {      
    case 'SpielPlaylist1':
      $PlaylistName = "Playlist1"; 
      foreach ($sonos->GetSONOSPlaylists() as $sonoslist){ 
         if ($sonoslist['title']==$PlaylistName){ 
            $PlaylistFILE= $sonoslist['file'];
            break; 
         } 
      } 
      $sonos->ClearQueue();
      $sonos->AddtoQueue("$PlaylistFILE"); 
      $sonos->SetQueue("x-rincon-queue:RINCON_"."***gelöscht***"."01400#0"); 
      $sonos->Play();
      break;

    case 'SpielPlaylist2':
 ..

Hallo Rainer,

vielen Dank für den Hinweis zum Posten von PHP-Code.

Hast Du auch eine Idee zum eigentlichen, technischen Problem mit GetSONOSPlaylists()?

Viele Grüße
Uwe

Da kann ich dir leider nicht weiterhelfen, aber es gibt ja einige Sonos-Spezialisten.

Hallo Uwe,

wie bereits von Chris erwähnt: Du verwendest PHPSonos, und das hat hier einen eigenen Thread.

Kurz um:
Ich verwende eine andere Methode um Soap aufzurufen. Ich ekomme dann die Soap antwort als Array und nicht als xml zurück. Mit der Antwort mache ich folgendes:


        foreach ((new SimpleXMLElement($sonos->BrowseContentDirectory('SQ:')['Result']))->container as $container) {
            if ($container->xpath('dc:title')[0] == $name){
              $uri = (string)$container->res;
              break;
            }
        }

Sprich:
Das Soap XML enthält ein weiteres XML in dem Tag „Result“. Das sieht so aus:


<?xml version="1.0"?>
<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/">
  <container id="SQ:2" parentID="SQ:" restricted="true">
    <dc:title>BestOf Giraffenaffen</dc:title>
    <res protocolInfo="file:*:audio/mpegurl:*">file:///jffs/settings/savedqueues.rsq#2</res>
    <upnp:class>object.container.playlistContainer</upnp:class>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a0nFquLADzZHucamzFtiX8p%3fsid%3d9%26flags%3d8224%26sn%3d1</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a2a1GRdSI562BSMI0vwUqwg%3fsid%3d9%26flags%3d8224%26sn%3d1</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a134XX6ee9NnvzZdrCdd6mQ%3fsid%3d9%26flags%3d8224%26sn%3d1</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a6Q920rgqXKV1MG3MxKCsa7%3fsid%3d9%26flags%3d8224%26sn%3d1</upnp:albumArtURI>
  </container>
  <container id="SQ:1" parentID="SQ:" restricted="true">
    <dc:title>Kinder</dc:title>
    <res protocolInfo="file:*:audio/mpegurl:*">file:///jffs/settings/savedqueues.rsq#1</res>
    <upnp:class>object.container.playlistContainer</upnp:class>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a0E1f6UjnDWKEkeykJbB87d%3fsid%3d9%26flags%3d32</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a2bqE903j0ibgiKMEjH0PmX%3fsid%3d9%26flags%3d32</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a3IVZA17cJpPvADtl3fgA60%3fsid%3d9%26flags%3d32</upnp:albumArtURI>
    <upnp:albumArtURI>/getaa?s=1&u=x-sonos-spotify%3aspotify%253atrack%253a65xIpwKmoD9omVbO06PIr9%3fsid%3d9%26flags%3d32</upnp:albumArtURI>
  </container>
</DIDL-Lite>

Kann sein, dass Deine PHPSonos Version eine ältere Version des XML erwartet, kann sein, dass Du es falsch interpretiertst.

–> Frage bitte in dem anderen Thread.

Gruß,
Thorsten

Ich hänge das mal an dieses Thema. Paßt hier ja wohl besser hin :slight_smile:

Michael

Hallo Torsten,

bis zur Sonor-Version 5.5 ging die Funktion GetSonosPlaylist bei mir. Die Funktion GetSonosPlaylists() in PHPSonos.inc.php ist bei mir wie folgt aufgebaut:


    //Liefert ein Array mit allen Sonos Wiedergabelisten und deren Aufrufinformationen
    public function GetSonosPlaylists()
    {
        $header='POST /MediaServer/ContentDirectory/Control HTTP/1.1
SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"
CONTENT-TYPE: text/xml; charset="utf-8"
HOST: '.$this->address.':1400';
$xml='<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:Browse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"><ObjectID>SQ:</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>0</StartingIndex><RequestedCount>100</RequestedCount><SortCriteria></SortCriteria></u:Browse>
</s:Body>
</s:Envelope>';
$content=$header . '
Content-Length: '. strlen($xml) .'

'. $xml;

echo "header=";
print_r($xml);

    $returnContent = $this->sendPacket($content);


echo "Content=";
print_r($content);
echo "<br>";

echo "returnContent=";
print_r($returnContent);
echo "<br>";

echo "Danach";

Es kommt gar kein Ergebnis zurück, so dass ich m.E. an der Sonos-Abfrage etwas geändert haben muss.

Viele Grüße
Uwe

Moin Uwe!

Für so UPnP Kram kann ich dir wärmstens dieses Tool empfehlen:
Intel® Software for UPnP* Technology: Technology Overview | Intel® Developer Zone

Noch 2 HowTo`s:
Quick Start Tutorial: DeviceSpy | Pelco Developer Network (PDN)
HOWTO - Device Spy - What your Renderer can really use - Universal Media Server | Forum

Damit habe ich mein „SonosBY“ gebaut und getestet. Da werden alle UPnP Geräte im Netzwerk gescannt und du kannst alle Funktionen sehen und testen :cool: Wenn du einen Befehl testen willst, einfach drauf gehen, INVOKE machen und mit F12 (oder rechte Maustaste und „Show Paket Capture“) kannst du dann die XML die er gesendet hat und die Antwort anschauen und sehen wo etwas schief laufen könnte.

Ab Sonos v6 war doch noch das Thema mit den zu großen Rückgaben, die dann in einzelne Chunks aufgeteilt werden…vlt. ist auch da das Problem zu suchen? Weil Sonos gibt immer etwas über UPnP zurück…selbst wenn man „Mist“ anfragt, dann kommt halt ein Fehler zurück.
Habe mich aber nicht wirklich mit PHPSonos beschäftigt, weil es mir persönlich zu schwer verständlich war vom Code. Vielleicht wird da was „falsches“ als Antwort auch verworfen.

Grüße,
Chris

Moin Chris,

vielen Dank für Deine guten Tips. Mit DeviceSpy konnte ich nachvollziehen, dass die SOAP-Action


POST /MediaServer/ContentDirectory/Control HTTP/1.1
SOAPACTION: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"

noch funktioniert und sinnvolle Playlisten zurück gibt.

Dann habe ich mir das Senden und Empfangen in PHPSonos.inc.php angeschaut und einen Debug-Modus aktiviert. Die Antwort sieht gut aus und es wird alles bis zum </DIDL-Lite> ausgegeben. Dennoch verarbeitet PHPSonos.inc.php es nicht und ich vermute Formatänderungen im Rückgabestring. Das muss ich mir detailliert anschauen.

Viele Grüsse
Uwe