TapHome

Sonos

Packet Parser → HTTP
Eingereicht von
Zuletzt aktualisiert: 03. 2026
Sonos

Sonos ist ein Premium-Wireless-Audiosystem für Multi-Room-Wiedergabe. TapHome kommuniziert mit Sonos-Lautsprechern über das lokale Netzwerk mittels UPnP/SOAP auf Port 1400 — keine Cloud-Verbindung oder Authentifizierung erforderlich. Die Vorlage ist universell und funktioniert mit allen Sonos-Lautsprechermodellen (Era 100, Era 300, One, Five, Beam, Arc, Ray, Move, Roam, Sub und weitere).

Die Vorlage bietet vollständige Wiedergabesteuerung (Play, Pause, Stop, Überspringen), Lautstärke- und Stummschaltungsverwaltung, Wiedergabemodus-Auswahl, Sleep-Timer und bis zu 10 Voreinstellungen für Playlists und Radiosender. 14 Service-Attribute zeigen Geräteinformationen und den aktuell gespielten Titel an.

Konfiguration

Der Sonos-Lautsprecher verbindet sich über WLAN. Geben Sie beim Import der TapHome-Vorlage die IP-Adresse des Lautsprechers ein (Standard-Platzhalter 192.168.0.1). Der Lautsprecher muss sich im selben Netzwerk wie die TapHome CCU befinden.

Sonos-Lautsprecher unterstützen mDNS-Discovery mit dem Hostnamen-Muster Sonos-{MAC}.local (MAC-Adresse ohne Doppelpunkte). Die Verwendung eines Hostnamens verhindert Verbindungsprobleme, wenn sich die IP-Adresse des Lautsprechers nach einer DHCP-Erneuerung ändert.

Öffnen Sie die TapHome-App und verwenden Sie den IP Scanner (Einstellungen → Netzwerk → Scannen). Der Scanner erkennt Geräte in Ihrem Netzwerk und zeigt sowohl die IP-Adresse als auch den mDNS-Hostnamen an (z. B. Sonos-B8E9375A1C02.local). Verwenden Sie den Hostnamen anstelle der IP-Adresse für eine zuverlässigere Verbindung.

Gerätefunktionen

Lautstärkeregelung

Die Vorlage stellt die Lautstärke als Dimmer dar. Die Lautstärke wird über die RenderingControl-SOAP-Aktion GetVolume (Bereich 0–100) gelesen und durch 100 geteilt, um den Dimmerwert 0,0–1,0 zu erzeugen. Das Schreiben einer neuen Lautstärke sendet SetVolume mit dem gewünschten Pegel. Die Lautstärke wird alle 2,5 Sekunden abgefragt.

Zwei zusätzliche Tasten — Volume Up und Volume Down — ermöglichen eine relative Lautstärkeanpassung. Diese werden durch CCU-seitige Logik verarbeitet, nicht durch direkte SOAP-Aktionen, was die Integration mit physischen Wandschaltern oder Smart Rules ermöglicht.

Stummschaltung

Die Stummschaltung ist als Schalter dargestellt. Der Zustand wird über GetMute gelesen und über SetMute auf dem Master-Kanal geschrieben. Bei aktivierter Stummschaltung wird die Audioausgabe ohne Änderung des Lautstärkepegels stummgeschaltet.

Wiedergabesteuerung

Sechs Tasten steuern den Wiedergabetransport:

  • Play — sendet AVTransport Play (Speed=1)
  • Pause — sendet AVTransport Pause
  • Stop — sendet AVTransport Stop
  • Next — sendet AVTransport Next zum Überspringen zum nächsten Titel
  • Previous — sendet AVTransport Previous zum Zurückspringen zum vorherigen Titel
  • Play/Pause — wechselt zwischen Play und Pause basierend auf dem aktuellen Transportzustand (verarbeitet durch CCU-seitige Logik)
Wiedergabestatus

Ein schreibgeschützter Binärsensor meldet, ob der Lautsprecher gerade wiedergibt. Die Vorlage liest GetTransportInfo und ordnet Transportzustände zu: PLAYING und TRANSITIONING werden auf 1 (Wiedergabe) gemappt, während STOPPED, NO_MEDIA_PRESENT und PAUSED_PLAYBACK auf 0 (keine Wiedergabe) gemappt werden. Abfrage alle 2,5 Sekunden.

Wiedergabemodus

Der Wiedergabemodus ist ein Mehrwertschalter mit sechs Modi:

WertModusBeschreibung
0NormalSequenzielle Wiedergabe
1Repeat AllGesamte Warteschlange wiederholen
2Repeat OneAktuellen Titel wiederholen
3Shuffle No RepeatZufallswiedergabe ohne Wiederholung
4ShuffleZufallswiedergabe mit Wiederholung
5Shuffle Repeat OneZufallswiedergabe, aktuellen Titel wiederholen

Die Werte 6–9 sind ungenutzte Platzhalter in der Mehrwertschalter-Konfiguration und haben keine Funktion.

Sleep-Timer

Zwei Tasten konfigurieren Sleep-Timer über die AVTransport-SOAP-Aktion ConfigureSleepTimer:

  • Sleep in 1 hour — setzt den Timer auf 01:00:00
  • Sleep in 15 minutes — setzt den Timer auf 00:15:00

Nach Ablauf des Timers stoppt der Lautsprecher die Wiedergabe automatisch.

Playlist- und Radio-Voreinstellungen

Die Vorlage bietet 10 Voreinstellungstasten — 5 für Playlists und 5 für Radiosender. Jede Taste hat eine Gerätevariable, die der Benutzer mit dem Namen der gewünschten Playlist oder des Senders konfigurieren muss. Das Skript übernimmt die Suche, Warteschlangenverwaltung und Wiedergabe automatisch.

Playlists (Tasten 1–5): Jede Playlist-Taste verwendet eine playlist_name-Gerätevariable. Das Skript durchsucht die Sonos-Playlists (Gespeicherte Warteschlangen) über den ContentDirectory-Container SQ:, mit exaktem dc:title-Abgleich (Groß-/Kleinschreibung wird beachtet). Bei einer Übereinstimmung leert das Skript die aktuelle Warteschlange, reiht die Playlist ein und startet die Wiedergabe.

Konfiguration einer Playlist-Taste:

  1. Öffnen Sie die TapHome-App → navigieren Sie zum Playlist-Gerät → Gerätevariablen
  2. Setzen Sie playlist_name auf den exakten Namen einer Sonos-Playlist
  3. Eine Sonos-Playlist erstellen: Sonos-App → Titel in die Warteschlange stellen → Warteschlange als Playlist speichern

Es werden nur Sonos-Playlists (Gespeicherte Warteschlangen) unterstützt. Playlists von Spotify, Apple Music oder anderen Streaming-Diensten können nicht direkt verwendet werden. Um Titel aus diesen Diensten zu verwenden, fügen Sie sie zuerst einer Sonos-Playlist hinzu.

Radiosender (Tasten 1–5): Jede Radio-Taste verwendet eine radio_name-Gerätevariable. Das Skript durchsucht die Sonos Favorites über den ContentDirectory-Container FV:2, mit exaktem dc:title-Abgleich (Groß-/Kleinschreibung wird beachtet) und Filterung nach dem Streaming-Radio-Protokoll (x-sonosapi-stream).

Konfiguration einer Radio-Taste:

  1. Öffnen Sie die TapHome-App → navigieren Sie zum Radio-Gerät → Gerätevariablen
  2. Setzen Sie radio_name auf den exakten Namen des Senders, wie er in den Sonos Favorites angezeigt wird
  3. Einen Sender zu den Favorites hinzufügen: Sonos-App → TuneIn oder iHeartRadio durchsuchen → auf das Herz-/Sternsymbol tippen

Der Name muss exakt übereinstimmen (Groß-/Kleinschreibung wird beachtet). Öffnen Sie die Sonos-App, gehen Sie zu My Sonos → Favorites und kopieren Sie den Sendernamen Zeichen für Zeichen. Es werden nur Streaming-Radiosender unterstützt — On-Demand-Audioinhalte aus den Favorites funktionieren nicht.

Service-Diagnostik

Die Vorlage zeigt 14 Service-Attribute aus der XML-Gerätebeschreibung (/xml/device_description.xml) an:

  • Geräteinformationen — Modellname, Modell-URL, Seriennummer, MAC-Adresse, Hostname, UDN (eindeutiger Gerätename)
  • Software — Softwareversion, Softwaregeneration, Hardwarerevision, API-Version, minimale API-Version
  • Sonos-Konfiguration — Raumname, Anzeigename
  • Aktueller Titel — aktueller Titel (Titel, Interpret, Album extrahiert aus DIDL-Lite-Metadaten über GetPositionInfo)

Das Attribut für den aktuellen Titel dekodiert die XML-kodierten TrackMetaData und gibt einen mehrzeiligen String mit Titel, Interpret und Albuminformationen zurück. Wenn die Metadaten nicht verfügbar sind (z. B. Line-in-Eingang), wird “Not supported” zurückgegeben.

Weitere Funktionen

Die Sonos UPnP-API bietet 16 Dienste mit Funktionen über die aktuelle Vorlagenimplementierung hinaus. Der RenderingControl-Dienst unterstützt Bass-, Höhen- und Lautstärkeanpassungen sowie den Nachtmodus bei Soundbar-Modellen. Der AVTransport-Dienst bietet Crossfade-Steuerung, Suche nach Zeit oder Titelnummer und vollständige Warteschlangenverwaltung (Titel hinzufügen, entfernen, neu ordnen). Multi-Room-Gruppenverwaltung, Alarmplanung und Equalizer-Einstellungen für Surround-/Subwoofer-Konfigurationen sind ebenfalls verfügbar. Tragbare Modelle (Move, Roam) zeigen den Batteriestatus an. Diese Funktionen können in einem zukünftigen Vorlagen-Update hinzugefügt werden.

Fehlerbehebung

Lautsprecher antwortet nicht
  1. Überprüfen Sie, ob der Sonos-Lautsprecher eingeschaltet und mit dem WLAN verbunden ist
  2. Versuchen Sie, den mDNS-Hostnamen (Sonos-{MAC}.local) anstelle der IP-Adresse zu verwenden — die IP könnte sich nach einer DHCP-Erneuerung geändert haben
  3. Öffnen Sie http://{speaker-ip}:1400/xml/device_description.xml im Browser — wenn XML zurückgegeben wird, ist der Lautsprecher erreichbar
  4. Prüfen Sie, ob TapHome CCU und der Sonos-Lautsprecher im selben Netzwerk / VLAN sind
Wiedergabebefehle schlagen mit Fehler 800 fehl

Sonos Multi-Room-Gruppen leiten alle Wiedergabebefehle über den Gruppenkoordinator. Wenn die Vorlage auf einen Lautsprecher zielt, der nicht der Koordinator ist, schlagen Transportbefehle (Play, Pause, Next, Previous) fehl. Stellen Sie sicher, dass die IP-Adresse in TapHome auf den Gruppenkoordinator zeigt, oder lösen Sie den Lautsprecher aus der Gruppe, um ihn zu einem eigenständigen Gerät zu machen.

Lautstärkeänderungen werden nicht übernommen
  1. Bestätigen Sie, dass die Vorlage abfragt — die Lautstärke wird alle 2,5 Sekunden über GetVolume gelesen
  2. Wenn ein anderer Controller (Sonos-App, Apple AirPlay) die Lautstärke geändert hat, übernimmt TapHome den neuen Wert beim nächsten Abfragezyklus
  3. Prüfen Sie, ob der Lautsprecher in einer Gruppe ist, in der die Lautstärke vom Gruppenkoordinator gesteuert wird

Sonos-Lautsprecher akzeptieren UPnP-Befehle nur von Geräten im selben Subnetz. Wenn sich die TapHome CCU in einem anderen VLAN befindet, stellen Sie sicher, dass Multicast-/UPnP-Verkehr zwischen den VLANs geroutet wird, oder platzieren Sie beide Geräte im selben Netzwerksegment.

Verfügbare Geräte

Sonos Modul
Serviceattribute
Modellname
Modell-URL
SW-Version
SW-Generation
HW-Revision
Seriennummer
MAC-Adresse
Hostname
UDN
API-Version
Min. API-Version
Raumname
Anzeigename
Aktueller Titel
Benutzerdefinierte Variablen
deviceDescription (string)

Sonos

Serviceattribute
Model name
VAR response := SENDHTTPREQUEST("/xml/device_description.xml");
deviceDescription := response.Content;

PARSEXML(deviceDescription, "//root:modelName[1]");
Model url
PARSEXML(deviceDescription, "//root:modelURL[1]");
SW version
PARSEXML(deviceDescription, "//root:softwareVersion[1]");
SW generation
PARSEXML(deviceDescription, "//root:swGen[1]");
HW revision
PARSEXML(deviceDescription, "//root:hardwareVersion[1]");
Serial number
PARSEXML(deviceDescription, "//root:serialNum[1]");
Mac address
PARSEXML(deviceDescription, "//root:MACAddress[1]");
Host name
VAR macAddress := PARSEXML(deviceDescription, "//root:MACAddress[1]");
"Sonos-" + REPLACE(macAddress, ":", "") + ".local"
UDN
PARSEXML(deviceDescription, "//root:UDN[1]");
API version
PARSEXML(deviceDescription, "//root:apiVersion[1]");
Min API version
PARSEXML(deviceDescription, "//root:minApiVersion[1]");
Room name
PARSEXML(deviceDescription, "//root:roomName[1]");
Display name
PARSEXML(deviceDescription, "//root:displayName[1]");
Current track
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo\"";
VAR body := "<?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:GetPositionInfo xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:GetPositionInfo></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    VAR metaData := DECODE(PARSETEXT(responseXml, "<TrackMetaData>", "</TrackMetaData>"), "xml");
    
    IF(metaData = "NOT_IMPLEMENTED")
        RETURN("Not supported");
    END

    IF(LENGTH(metaData) = 0)
        RETURN("");
    END

    VAR title := PARSEXML(metaData, "//dc:title");
    VAR artist := PARSEXML(metaData, "//dc:creator");
    VAR album := PARSEXML(metaData, "//upnp:album");
    
    VAR result := "";
    
    IF(LENGTH(title) > 0)
        result := "Title: " + title + "\n";
    END
    
    IF(LENGTH(artist) > 0)
         result := result + "Artist: " + artist + "\n";
    END
    
    IF(LENGTH(album) > 0)
        result := result + "Album: " + album;
    END

    RETURN(result);
ELSE
    RETURN("Error");
END
Lautstärke Dimmer
numeric Einheit: %

Lautstärke

Level lesen
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#GetVolume\"";
VAR body := "<?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:GetVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetVolume></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    RETURN(PARSEXML(responseXml, "//CurrentVolume") / 100.0);
ELSE
    ADDERROR(response.Content);
    RETURN(NaN);
END
Level schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#SetVolume\"";
VAR body := "<?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:SetVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>" + ROUND(Le*100) + "</DesiredVolume></u:SetVolume></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);
Nächster Titel Taster
action

Nächster Titel

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Next\"";
VAR body := "<?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:Next xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Next></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Pause Taster
action

Pause

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Pause\"";
VAR body := "<?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:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Pause></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Play Taster
action

Play

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
VAR body := "<?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:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Vorheriger Titel Taster
action

Vorheriger Titel

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Previous\"";
VAR body := "<?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:Previous xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Previous></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Stop Taster
action

Stop

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Stop\"";
VAR body := "<?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:Stop xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Stop></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Lauter Taster
action

Lauter

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#SetRelativeVolume\"";

VAR body := "<?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:SetRelativeVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel><Adjustment>5</Adjustment></u:SetRelativeVolume></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);
Leiser Taster
action

Leiser

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#SetRelativeVolume\"";

VAR body := "<?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:SetRelativeVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel><Adjustment>-5</Adjustment></u:SetRelativeVolume></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);
Stummschaltung Schalter
boolean
Werte / Zustände: ON · OFF

Stummschaltung

Schaltzustand lesen
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#GetMute\"";
VAR body := "<?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:GetMute xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetMute></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    RETURN(PARSEXML(responseXml, "//CurrentMute"));
ELSE
    ADDERROR(response.Content);
    RETURN(NaN);
END
Schaltzustand schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:RenderingControl:1#SetMute\"";
VAR body := "<?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:SetMute xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel><DesiredMute>" + St + "</DesiredMute></u:SetMute></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/RenderingControl/Control", "POST", body, header);
Wiedergabemodus Mehrwertschalter
enum mapped
Werte / Zustände: Normal · Repeat all · Repeat one · Shuffle no repeat · Shuffle · Shuffle repeat one

Wiedergabemodus

Schaltzustand lesen
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#GetTransportSettings\"";
VAR body := "<?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:GetTransportSettings xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:GetTransportSettings></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    VAR mode := PARSEXML(responseXml, "//PlayMode");
    RETURN(SWITCH(mode , "NORMAL", 0, "REPEAT_ALL", 1, "REPEAT_ONE", 2, "SHUFFLE_NOREPEAT", 3, "SHUFFLE", 4, "SHUFFLE_REPEAT_ONE", 5, -1));
ELSE
    ADDERROR(response.Content);
    RETURN(NaN);
END
Schaltzustand schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetPlayMode\"";

VAR mode := SWITCH(Mu, 0, "NORMAL", 1, "REPEAT_ALL", 2, "REPEAT_ONE", 3, "SHUFFLE_NOREPEAT", 4, "SHUFFLE", 5, "SHUFFLE_REPEAT_ONE", "NORMAL");

VAR body := "<?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:SetPlayMode xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><NewPlayMode>" + mode +"</NewPlayMode></u:SetPlayMode></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Sleep-Timer (1 Stunde) Taster
action

Sleep-Timer (1 Stunde)

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#ConfigureSleepTimer\"";

VAR body := "<?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:ConfigureSleepTimer xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><NewSleepTimerDuration>01:00:00</NewSleepTimerDuration></u:ConfigureSleepTimer></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Sleep-Timer (15 Min.) Taster
action

Sleep-Timer (15 Min.)

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#ConfigureSleepTimer\"";

VAR body := "<?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:ConfigureSleepTimer xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><NewSleepTimerDuration>00:15:00</NewSleepTimerDuration></u:ConfigureSleepTimer></s:Body></s:Envelope>";

SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
Wiedergabestatus Reed-Kontakt Nur lesen
boolean mapped

Wiedergabestatus

Lesen
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo\"";
VAR body := "<?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:GetTransportInfo xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:GetTransportInfo></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    VAR state := PARSEXML(responseXml, "//CurrentTransportState");
    RETURN(SWITCH(state , "PLAYING", 1, "TRANSITIONING", 1, "STOPPED", 0, "NO_MEDIA_PRESENT", 0, "PAUSED_PLAYBACK", 0, 0));
ELSE
    ADDERROR(response.Content);
    RETURN(NaN);
END
Play/Pause Taster
action

Play/Pause

Tastenstatus schreiben
VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo\"";
VAR body := "<?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:GetTransportInfo xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:GetTransportInfo></s:Body></s:Envelope>";

VAR response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);

IF response.IsSuccess
    VAR responseXml := response.Content;
    VAR state := PARSEXML(responseXml, "//CurrentTransportState");
    VAR isPlaying := SWITCH(state , "PLAYING", 1, "TRANSITIONING", 1, "STOPPED", 0, "NO_MEDIA_PRESENT", 0, "PAUSED_PLAYBACK", 0, 0);
    
    IF(isPlaying)
        VAR headerPause := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Pause\"";
        VAR bodyPause := "<?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:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Pause></s:Body></s:Envelope>";

        SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", bodyPause, headerPause);
    ELSE
        VAR headerPlay := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
        VAR bodyPlay := "<?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:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

        SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", bodyPlay, headerPlay);
    END
ELSE
    ADDERROR(response.Content);
    RETURN(NaN);
END
Playlist 1 Taster
action
Variable: playlist_nameExact name of a Sonos playlist (Saved Queue). Case-sensitive.

Playlist 1

Tastenstatus schreiben
######################
# check playlist name is not empty
IF(ISNULL(playlist_name) OR LENGTH(playlist_name) = 0)
   ADDERROR("Please set playlist name in device variables");
   RETURN(-1);
END

######################
# get player uuid
VAR response := SENDHTTPREQUEST("xml/device_description.xml");
VAR content := response.Content;
VAR playerUuid := PARSETEXT(content, "<UDN>uuid:", "</UDN>");

IF(ISNULL(playerUuid))
    ADDERROR("Failed to get player UUID");
    RETURN(-2);
END
######################

######################
# fetch playlists
VAR playlistUri := NULL;
VAR numberOfPlaylists := -1;
VAR readPlaylists := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>" + readPlaylists + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    content := response.Content;
    
    IF(numberOfPlaylists = -1)
        numberOfPlaylists := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedPlaylists := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readPlaylists := readPlaylists + returnedPlaylists;
    
    VAR playlistsXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    playlistUri := PARSEXML(playlistsXml, "//DIDL-Lite:container[dc:title='" + playlist_name + "']/DIDL-Lite:res");
    
    IF(!ISNULL(playlistUri) AND LENGTH(playlistUri) > 0)
        BREAK;
    END
LOOP WHILE readPlaylists < numberOfPlaylists
    
######################
IF(ISNULL(playlistUri) OR LENGTH(playlistUri) = 0)
    ADDERROR("Unable to find playlist with name '" + playlist_name + "'. Only Sonos playlists are supported.");
    RETURN(-3);
END

######################
# clear play queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#RemoveAllTracksFromQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:RemoveAllTracksFromQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:RemoveAllTracksFromQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to RemoveAllTracksFromQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-4);
END
######################

######################
# add playlist to queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#AddURIToQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:AddURIToQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><EnqueuedURI>" + playlistUri + "</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>0</EnqueueAsNext></u:AddURIToQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to AddURIToQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-5);
END
######################

######################
# set play uri
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>x-rincon-queue:" + playerUuid + "#0</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-6);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-7);
END
######################
Playlist 2 Taster
action
Variable: playlist_nameExact name of a Sonos playlist (Saved Queue). Case-sensitive.

Playlist 2

Tastenstatus schreiben
######################
# check playlist name is not empty
IF(ISNULL(playlist_name) OR LENGTH(playlist_name) = 0)
   ADDERROR("Please set playlist name in device variables");
   RETURN(-1);
END

######################
# get player uuid
VAR response := SENDHTTPREQUEST("xml/device_description.xml");
VAR content := response.Content;
VAR playerUuid := PARSETEXT(content, "<UDN>uuid:", "</UDN>");

IF(ISNULL(playerUuid))
    ADDERROR("Failed to get player UUID");
    RETURN(-2);
END
######################

######################
# fetch playlists
VAR playlistUri := NULL;
VAR numberOfPlaylists := -1;
VAR readPlaylists := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>" + readPlaylists + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    content := response.Content;
    
    IF(numberOfPlaylists = -1)
        numberOfPlaylists := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedPlaylists := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readPlaylists := readPlaylists + returnedPlaylists;
    
    VAR playlistsXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    playlistUri := PARSEXML(playlistsXml, "//DIDL-Lite:container[dc:title='" + playlist_name + "']/DIDL-Lite:res");
    
    IF(!ISNULL(playlistUri) AND LENGTH(playlistUri) > 0)
        BREAK;
    END
LOOP WHILE readPlaylists < numberOfPlaylists
    
######################
IF(ISNULL(playlistUri) OR LENGTH(playlistUri) = 0)
    ADDERROR("Unable to find playlist with name '" + playlist_name + "'. Only Sonos playlists are supported.");
    RETURN(-3);
END

######################
# clear play queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#RemoveAllTracksFromQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:RemoveAllTracksFromQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:RemoveAllTracksFromQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to RemoveAllTracksFromQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-4);
END
######################

######################
# add playlist to queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#AddURIToQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:AddURIToQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><EnqueuedURI>" + playlistUri + "</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>0</EnqueueAsNext></u:AddURIToQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to AddURIToQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-5);
END
######################

######################
# set play uri
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>x-rincon-queue:" + playerUuid + "#0</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-6);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-7);
END
######################
Playlist 3 Taster
action
Variable: playlist_nameExact name of a Sonos playlist (Saved Queue). Case-sensitive.

Playlist 3

Tastenstatus schreiben
######################
# check playlist name is not empty
IF(ISNULL(playlist_name) OR LENGTH(playlist_name) = 0)
   ADDERROR("Please set playlist name in device variables");
   RETURN(-1);
END

######################
# get player uuid
VAR response := SENDHTTPREQUEST("xml/device_description.xml");
VAR content := response.Content;
VAR playerUuid := PARSETEXT(content, "<UDN>uuid:", "</UDN>");

IF(ISNULL(playerUuid))
    ADDERROR("Failed to get player UUID");
    RETURN(-2);
END
######################

######################
# fetch playlists
VAR playlistUri := NULL;
VAR numberOfPlaylists := -1;
VAR readPlaylists := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>" + readPlaylists + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    content := response.Content;
    
    IF(numberOfPlaylists = -1)
        numberOfPlaylists := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedPlaylists := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readPlaylists := readPlaylists + returnedPlaylists;
    
    VAR playlistsXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    playlistUri := PARSEXML(playlistsXml, "//DIDL-Lite:container[dc:title='" + playlist_name + "']/DIDL-Lite:res");
    
    IF(!ISNULL(playlistUri) AND LENGTH(playlistUri) > 0)
        BREAK;
    END
LOOP WHILE readPlaylists < numberOfPlaylists
    
######################
IF(ISNULL(playlistUri) OR LENGTH(playlistUri) = 0)
    ADDERROR("Unable to find playlist with name '" + playlist_name + "'. Only Sonos playlists are supported.");
    RETURN(-3);
END

######################
# clear play queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#RemoveAllTracksFromQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:RemoveAllTracksFromQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:RemoveAllTracksFromQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to RemoveAllTracksFromQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-4);
END
######################

######################
# add playlist to queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#AddURIToQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:AddURIToQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><EnqueuedURI>" + playlistUri + "</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>0</EnqueueAsNext></u:AddURIToQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to AddURIToQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-5);
END
######################

######################
# set play uri
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>x-rincon-queue:" + playerUuid + "#0</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-6);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-7);
END
######################
Playlist 4 Taster
action
Variable: playlist_nameExact name of a Sonos playlist (Saved Queue). Case-sensitive.

Playlist 4

Tastenstatus schreiben
######################
# check playlist name is not empty
IF(ISNULL(playlist_name) OR LENGTH(playlist_name) = 0)
   ADDERROR("Please set playlist name in device variables");
   RETURN(-1);
END

######################
# get player uuid
VAR response := SENDHTTPREQUEST("xml/device_description.xml");
VAR content := response.Content;
VAR playerUuid := PARSETEXT(content, "<UDN>uuid:", "</UDN>");

IF(ISNULL(playerUuid))
    ADDERROR("Failed to get player UUID");
    RETURN(-2);
END
######################

######################
# fetch playlists
VAR playlistUri := NULL;
VAR numberOfPlaylists := -1;
VAR readPlaylists := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>" + readPlaylists + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    content := response.Content;
    
    IF(numberOfPlaylists = -1)
        numberOfPlaylists := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedPlaylists := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readPlaylists := readPlaylists + returnedPlaylists;
    
    VAR playlistsXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    playlistUri := PARSEXML(playlistsXml, "//DIDL-Lite:container[dc:title='" + playlist_name + "']/DIDL-Lite:res");
    
    IF(!ISNULL(playlistUri) AND LENGTH(playlistUri) > 0)
        BREAK;
    END
LOOP WHILE readPlaylists < numberOfPlaylists
    
######################
IF(ISNULL(playlistUri) OR LENGTH(playlistUri) = 0)
    ADDERROR("Unable to find playlist with name '" + playlist_name + "'. Only Sonos playlists are supported.");
    RETURN(-3);
END

######################
# clear play queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#RemoveAllTracksFromQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:RemoveAllTracksFromQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:RemoveAllTracksFromQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to RemoveAllTracksFromQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-4);
END
######################

######################
# add playlist to queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#AddURIToQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:AddURIToQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><EnqueuedURI>" + playlistUri + "</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>0</EnqueueAsNext></u:AddURIToQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to AddURIToQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-5);
END
######################

######################
# set play uri
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>x-rincon-queue:" + playerUuid + "#0</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-6);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-7);
END
######################
Playlist 5 Taster
action
Variable: playlist_nameExact name of a Sonos playlist (Saved Queue). Case-sensitive.

Playlist 5

Tastenstatus schreiben
######################
# check playlist name is not empty
IF(ISNULL(playlist_name) OR LENGTH(playlist_name) = 0)
   ADDERROR("Please set playlist name in device variables");
   RETURN(-1);
END

######################
# get player uuid
VAR response := SENDHTTPREQUEST("xml/device_description.xml");
VAR content := response.Content;
VAR playerUuid := PARSETEXT(content, "<UDN>uuid:", "</UDN>");

IF(ISNULL(playerUuid))
    ADDERROR("Failed to get player UUID");
    RETURN(-2);
END
######################

######################
# fetch playlists
VAR playlistUri := NULL;
VAR numberOfPlaylists := -1;
VAR readPlaylists := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>" + readPlaylists + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    content := response.Content;
    
    IF(numberOfPlaylists = -1)
        numberOfPlaylists := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedPlaylists := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readPlaylists := readPlaylists + returnedPlaylists;
    
    VAR playlistsXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    playlistUri := PARSEXML(playlistsXml, "//DIDL-Lite:container[dc:title='" + playlist_name + "']/DIDL-Lite:res");
    
    IF(!ISNULL(playlistUri) AND LENGTH(playlistUri) > 0)
        BREAK;
    END
LOOP WHILE readPlaylists < numberOfPlaylists
    
######################
IF(ISNULL(playlistUri) OR LENGTH(playlistUri) = 0)
    ADDERROR("Unable to find playlist with name '" + playlist_name + "'. Only Sonos playlists are supported.");
    RETURN(-3);
END

######################
# clear play queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#RemoveAllTracksFromQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:RemoveAllTracksFromQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:RemoveAllTracksFromQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to RemoveAllTracksFromQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-4);
END
######################

######################
# add playlist to queue
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#AddURIToQueue\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:AddURIToQueue xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><EnqueuedURI>" + playlistUri + "</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>0</EnqueueAsNext></u:AddURIToQueue></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to AddURIToQueue (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-5);
END
######################

######################
# set play uri
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>x-rincon-queue:" + playerUuid + "#0</CurrentURI><CurrentURIMetaData></CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-6);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
    ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
    RETURN(-7);
END
######################
Radiosender 1 Taster
action
Variable: radio_nameExact name of a radio station from Sonos Favorites. Case-sensitive.

Radiosender 1

Tastenstatus schreiben
######################
# check radio name is not empty
IF(ISNULL(radio_name) OR LENGTH(radio_name) = 0)
   ADDERROR("Please set radio name in device variables");
   RETURN(-1);
END

######################
# fetch favorites
VAR radioUri := NULL;
VAR numberOfFavorites := -1;
VAR readFavorites := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>FV:2</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>" + readFavorites + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    VAR response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    VAR content := response.Content;
   
    IF(numberOfFavorites = -1)
        numberOfFavorites := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedFavorites := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readFavorites := readFavorites + returnedFavorites;
    
    VAR favoritesXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    radioUri := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "']/DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']");
    
    IF(!ISNULL(radioUri) AND LENGTH(radioUri) > 0)
        BREAK;
    END
LOOP WHILE readFavorites < numberOfFavorites

IF(ISNULL(radioUri) OR LENGTH(radioUri) = 0)
    ADDERROR("Unable to find radio with name '" + radio_name + "'. Make sure it's included in your Sonos favorite radio stations");
    RETURN(-3);
END

######################
# find radio metadata
VAR radioMetaData := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "'and DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']]/r:resMD");

IF(ISNULL(radioMetaData) OR LENGTH(radioMetaData) = 0)
	ADDERROR("Unable to find radio metadata");
	RETURN(-4);
END

######################
# set radio uri
VAR metaDataEncoded := ENCODE(radioMetaData, "xml");
VAR uriEncoded := ENCODE(radioUri, "xml");

header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>" + uriEncoded + "</CurrentURI><CurrentURIMetaData>" + metaDataEncoded + "</CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-5);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-6);
END
######################
Radiosender 2 Taster
action
Variable: radio_nameExact name of a radio station from Sonos Favorites. Case-sensitive.

Radiosender 2

Tastenstatus schreiben
######################
# check radio name is not empty
IF(ISNULL(radio_name) OR LENGTH(radio_name) = 0)
   ADDERROR("Please set radio name in device variables");
   RETURN(-1);
END

######################
# fetch favorites
VAR radioUri := NULL;
VAR numberOfFavorites := -1;
VAR readFavorites := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>FV:2</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>" + readFavorites + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    VAR response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    VAR content := response.Content;
   
    IF(numberOfFavorites = -1)
        numberOfFavorites := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedFavorites := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readFavorites := readFavorites + returnedFavorites;
    
    VAR favoritesXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    radioUri := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "']/DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']");
    
    IF(!ISNULL(radioUri) AND LENGTH(radioUri) > 0)
        BREAK;
    END
LOOP WHILE readFavorites < numberOfFavorites

IF(ISNULL(radioUri) OR LENGTH(radioUri) = 0)
    ADDERROR("Unable to find radio with name '" + radio_name + "'. Make sure it's included in your Sonos favorite radio stations");
    RETURN(-3);
END

######################
# find radio metadata
VAR radioMetaData := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "'and DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']]/r:resMD");

IF(ISNULL(radioMetaData) OR LENGTH(radioMetaData) = 0)
	ADDERROR("Unable to find radio metadata");
	RETURN(-4);
END

######################
# set radio uri
VAR metaDataEncoded := ENCODE(radioMetaData, "xml");
VAR uriEncoded := ENCODE(radioUri, "xml");

header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>" + uriEncoded + "</CurrentURI><CurrentURIMetaData>" + metaDataEncoded + "</CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-5);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-6);
END
######################
Radiosender 3 Taster
action
Variable: radio_nameExact name of a radio station from Sonos Favorites. Case-sensitive.

Radiosender 3

Tastenstatus schreiben
######################
# check radio name is not empty
IF(ISNULL(radio_name) OR LENGTH(radio_name) = 0)
   ADDERROR("Please set radio name in device variables");
   RETURN(-1);
END

######################
# fetch favorites
VAR radioUri := NULL;
VAR numberOfFavorites := -1;
VAR readFavorites := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>FV:2</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>" + readFavorites + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    VAR response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    VAR content := response.Content;
   
    IF(numberOfFavorites = -1)
        numberOfFavorites := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedFavorites := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readFavorites := readFavorites + returnedFavorites;
    
    VAR favoritesXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    radioUri := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "']/DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']");
    
    IF(!ISNULL(radioUri) AND LENGTH(radioUri) > 0)
        BREAK;
    END
LOOP WHILE readFavorites < numberOfFavorites

IF(ISNULL(radioUri) OR LENGTH(radioUri) = 0)
    ADDERROR("Unable to find radio with name '" + radio_name + "'. Make sure it's included in your Sonos favorite radio stations");
    RETURN(-3);
END

######################
# find radio metadata
VAR radioMetaData := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "'and DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']]/r:resMD");

IF(ISNULL(radioMetaData) OR LENGTH(radioMetaData) = 0)
	ADDERROR("Unable to find radio metadata");
	RETURN(-4);
END

######################
# set radio uri
VAR metaDataEncoded := ENCODE(radioMetaData, "xml");
VAR uriEncoded := ENCODE(radioUri, "xml");

header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>" + uriEncoded + "</CurrentURI><CurrentURIMetaData>" + metaDataEncoded + "</CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-5);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-6);
END
######################
Radiosender 4 Taster
action
Variable: radio_nameExact name of a radio station from Sonos Favorites. Case-sensitive.

Radiosender 4

Tastenstatus schreiben
######################
# check radio name is not empty
IF(ISNULL(radio_name) OR LENGTH(radio_name) = 0)
   ADDERROR("Please set radio name in device variables");
   RETURN(-1);
END

######################
# fetch favorites
VAR radioUri := NULL;
VAR numberOfFavorites := -1;
VAR readFavorites := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>FV:2</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>" + readFavorites + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    VAR response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    VAR content := response.Content;
   
    IF(numberOfFavorites = -1)
        numberOfFavorites := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedFavorites := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readFavorites := readFavorites + returnedFavorites;
    
    VAR favoritesXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    radioUri := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "']/DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']");
    
    IF(!ISNULL(radioUri) AND LENGTH(radioUri) > 0)
        BREAK;
    END
LOOP WHILE readFavorites < numberOfFavorites

IF(ISNULL(radioUri) OR LENGTH(radioUri) = 0)
    ADDERROR("Unable to find radio with name '" + radio_name + "'. Make sure it's included in your Sonos favorite radio stations");
    RETURN(-3);
END

######################
# find radio metadata
VAR radioMetaData := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "'and DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']]/r:resMD");

IF(ISNULL(radioMetaData) OR LENGTH(radioMetaData) = 0)
	ADDERROR("Unable to find radio metadata");
	RETURN(-4);
END

######################
# set radio uri
VAR metaDataEncoded := ENCODE(radioMetaData, "xml");
VAR uriEncoded := ENCODE(radioUri, "xml");

header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>" + uriEncoded + "</CurrentURI><CurrentURIMetaData>" + metaDataEncoded + "</CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-5);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-6);
END
######################
Radiosender 5 Taster
action
Variable: radio_nameExact name of a radio station from Sonos Favorites. Case-sensitive.

Radiosender 5

Tastenstatus schreiben
######################
# check radio name is not empty
IF(ISNULL(radio_name) OR LENGTH(radio_name) = 0)
   ADDERROR("Please set radio name in device variables");
   RETURN(-1);
END

######################
# fetch favorites
VAR radioUri := NULL;
VAR numberOfFavorites := -1;
VAR readFavorites := 0;

DO
    VAR header := "SOAPACTION: \"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"";
    VAR body := "<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>FV:2</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter></Filter><StartingIndex>" + readFavorites + "</StartingIndex><RequestedCount>10</RequestedCount><SortCriteria></SortCriteria></u:Browse></s:Body></s:Envelope>";

    VAR response := SENDHTTPREQUEST("MediaServer/ContentDirectory/Control", "POST", body, header);
    VAR content := response.Content;
   
    IF(numberOfFavorites = -1)
        numberOfFavorites := TODOUBLE(PARSETEXT(content, "<TotalMatches>", "</TotalMatches>"));
    END
    
    VAR returnedFavorites := TODOUBLE(PARSETEXT(content, "<NumberReturned>", "</NumberReturned>"));
    readFavorites := readFavorites + returnedFavorites;
    
    VAR favoritesXml := DECODE(PARSETEXT(content, "<Result>", "</Result>"), "xml");
    radioUri := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "']/DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']");
    
    IF(!ISNULL(radioUri) AND LENGTH(radioUri) > 0)
        BREAK;
    END
LOOP WHILE readFavorites < numberOfFavorites

IF(ISNULL(radioUri) OR LENGTH(radioUri) = 0)
    ADDERROR("Unable to find radio with name '" + radio_name + "'. Make sure it's included in your Sonos favorite radio stations");
    RETURN(-3);
END

######################
# find radio metadata
VAR radioMetaData := PARSEXML(favoritesXml, "//DIDL-Lite:item[dc:title='" + radio_name + "'and DIDL-Lite:res[@protocolInfo='x-sonosapi-stream:*:*:*']]/r:resMD");

IF(ISNULL(radioMetaData) OR LENGTH(radioMetaData) = 0)
	ADDERROR("Unable to find radio metadata");
	RETURN(-4);
END

######################
# set radio uri
VAR metaDataEncoded := ENCODE(radioMetaData, "xml");
VAR uriEncoded := ENCODE(radioUri, "xml");

header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><CurrentURI>" + uriEncoded + "</CurrentURI><CurrentURIMetaData>" + metaDataEncoded + "</CurrentURIMetaData></u:SetAVTransportURI></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to SetAVTransportURI (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-5);
END
######################

######################
# play
header := "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#Play\"";
body := "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play></s:Body></s:Envelope>";

response := SENDHTTPREQUEST("MediaRenderer/AVTransport/Control", "POST", body, header);
IF(!response.IsSuccess)
	ADDERROR("Unable to Play (" + PARSEJSON(response, "Content", 1) + ")");
	RETURN(-6);
END
######################
Verbindung: Packet Parser → HTTP
Mögliche Verbesserungen (14)
  • Bass control — Adjustable bass level -10 to 10
  • Treble control — Adjustable treble level -10 to 10
  • Loudness compensation — Boolean loudness on/off
  • Night mode — Boolean night mode (reduced dynamics), available on soundbar models
  • Crossfade — Boolean crossfade on/off between tracks
  • Seek (time/track) — Seek by TRACK_NR, REL_TIME, or TIME_DELTA
  • Queue management — Full queue CRUD — add, remove, reorder tracks
  • Group management — Multi-room group join/leave/delegate coordinator
  • Alarm management — Create, edit, delete alarms on the speaker
  • Battery status — Battery data available on portable models only (Move, Roam)
  • Relative volume — Increment/decrement volume by delta value
  • Sleep timer remaining — Read remaining sleep timer duration (hh:mm:ss)
  • Surround/Sub EQ — Subwoofer gain, surround level, height channel — available on multi-speaker setups
  • LED control — Status LED on/off

Quellen