Libratone Zipp WLan Lautsprecher

Die WLan Lautsprecher von Libratone (Zipp, Zipp Mini, Zipp 2 und Zipp 2 Mini) lassen sich mit UDP Paketen recht simpel steuern. Einige Nachforschungen via Wireshark, Reverse-Engineering der App und simplen Testverfahren, konnte ich bisher einige Befehle herausfinden, die dann via Loxone steuerbar sind. Die Befehle können via Hex-Code als UDP Paket übermittelt werden. Nachfolgend eine Tabelle mit einem Auszug der möglichen Kommandos mit einer kurzen Beschreibung. In Loxone kann ein Libratone Lautsprecher dann via virtuellem Ausgang und Ausgangsbefehlen verwendet werden. Eine Vorlage dazu habe ich dem Artikel weiter unten angehängt.

Voraussetzung zur Nutzung einer Libratone WLan Box via Loxone:

  • Libratone Box ist bereits im gleichen Netzwerk wie Loxone vorhanden (WLan ist bereits eingerichtet)

Auszug einiger Befehle

Nachfolgend befindet sich eine Liste mit möglichen Kommandos, mit denen man die Libratone Box problemlos über WLan steuern kann.

Name

Befehl (Hex-Code)

Beschreibung

Name

Befehl (Hex-Code)

Beschreibung

Favorit 1

\x00\x00\x02\x01\x15\x00\x00\x00\x00\x77\x7b\x22\x69\x73\x46\x72\x6f\x6d\x43\x68\x61\x6e\x6e
\x65\x6c\x22\x3a\x66\x61\x6c\x73\x65\x2c\x22\x70\x6c\x61\x79\x5f\x69\x64\x65\x6e\x74\x69\x74
\x79\x22\x3a\x22\x31\x22\x2c\x22\x70\x6c\x61\x79\x5f\x73\x75\x62\x74\x69\x74\x6c\x65\x22\x3a
\x22\x31\x22\x2c\x22\x70\x6c\x61\x79\x5f\x74\x69\x74\x6c\x65\x22\x3a\x22\x63\x68\x61\x6e\x6e
\x65\x6c\x22\x2c\x22\x70\x6c\x61\x79\x5f\x74\x79\x70\x65\x22\x3a\x22\x63\x68\x61\x6e\x6e\x65
\x6c\x22\x2c\x22\x74\x6f\x6b\x65\x6e\x22\x3a\x22\x22\x7d

Wählt den Radiosender, der als erster Favorit gespeichert wurde

Favorit 2

\x00\x00\x02\x01\x15\x00\x00\x00\x00\x77\x7b\x22\x69\x73\x46\x72\x6f\x6d\x43\x68\x61\x6e\x6e
\x65\x6c\x22\x3a\x66\x61\x6c\x73\x65\x2c\x22\x70\x6c\x61\x79\x5f\x69\x64\x65\x6e\x74\x69\x74
\x79\x22\x3a\x22\x32\x22\x2c\x22\x70\x6c\x61\x79\x5f\x73\x75\x62\x74\x69\x74\x6c\x65\x22\x3a
\x22\x32\x22\x2c\x22\x70\x6c\x61\x79\x5f\x74\x69\x74\x6c\x65\x22\x3a\x22\x63\x68\x61\x6e\x6e
\x65\x6c\x22\x2c\x22\x70\x6c\x61\x79\x5f\x74\x79\x70\x65\x22\x3a\x22\x63\x68\x61\x6e\x6e\x65
\x6c\x22\x2c\x22\x74\x6f\x6b\x65\x6e\x22\x3a\x22\x22\x7d

Wählt den Radiosender, der als zweiter Favorit gespeichert wurde

...

weitere Favoriten in Vorlage (*.xml) vorhanden...

...

Play

\x00\x00\x02\x00\x28\x00\x00\x00\x00\x04\x50\x4c\x41\x59

Startet einen Stream, wenn bspw. vorher der Radio-Stream mit Pause gestoppt wurde

Stop/Pause

\x00\x00\x02\x00\x28\x00\x00\x00\x00\x04\x53\x54\x4f\x50

Pausiert oder stoppt einen gerade laufenden Stream

...

weitere Befehle in Vorlage (*.xml) vorhanden...

...

Standby

\x00\x00\x02\x00\x0f\x00\x00\x00\x00\x02\x32\x30

Versetzt die Libratone Box sofort in Standby

Standby Timer 15min.

\x00\x00\x02\x00\x0f\x00\x00\x00\x00\x04\x32\x39\x30\x30

Startet einen internen Timer, der die Box nach 15 Minuten in den Standby versetzt

Standby Timer 30min.

\x00\x00\x02\x00\x0f\x00\x00\x00\x00\x05\x32\x31\x38\x30\x30

Startet einen internen Timer, der die Box nach 30 Minuten in den Standby versetzt

...

weitere Standby Timer in Vorlage (*.xml) vorhanden...

...

Standby Timer abbrechen

\x00\x00\x02\x00\x0f\x00\x00\x00\x00\x02\x46\x30

Unterbricht der gerade laufenden Standby Timer

Ton: Neutral

\x00\x00\x02\x02\x06\x00\x00\x00\x00\x04\x56\x31\x30\x30

Neutrale Grundeinstellung

Ton: Easy Listening

\x00\x00\x02\x02\x06\x00\x00\x00\x00\x04\x56\x31\x30\x31

Leichter und entspannter Sound

...

weitere Toneinstellungen in Vorlage (*.xml) vorhanden...

...

Raum: Neutral

\x00\x00\x02\x02\x07\x00\x00\x00\x00\x07\x6e\x65\x75\x74\x72\x61\x6c

Neutrale Grundeinstellung

Raum: Im Freien

\x00\x00\x02\x02\x07\x00\x00\x00\x00\x07\x6f\x75\x74\x64\x6f\x6f\x72

Optimales Klangfeld, wenn das Produkt im Freien steht

...

weitere Raumeinstellungen in Vorlage (*.xml) vorhanden...

...

LED immer an (on)

\x00\x00\x02\x02\x65\x00\x00\x00\x00\x01\x30

Die LED Beleuchtung wird auf "immer an" geschalten

LED immer an (off)

\x00\x00\x02\x02\x65\x00\x00\x00\x00\x01\x31

Die LED Beleuchtung geht nach ein paar Sekunden aus und nur bei Bedienung kurz an

LED Helligkeit 0

\x00\x00\x02\x01\x2d\x00\x00\x00\x00\x01\x30

LED Helligkeit auf 0% (aus)

LED Helligkeit 1

\x00\x00\x02\x01\x2d\x00\x00\x00\x00\x01\x31

LED Helligkeit auf 1%

LED Helligkeit 2

\x00\x00\x02\x01\x2d\x00\x00\x00\x00\x01\x32

LED Helligkeit auf 2%

...

weitere LED Helligkeiten in Vorlage (*.xml) vorhanden...

...

LED Helligkeit 50

\x00\x00\x02\x01\x2d\x00\x00\x00\x00\x02\x35\x30

LED Helligkeit auf 50%

...

weitere LED Helligkeiten in Vorlage (*.xml) vorhanden...

...

LED Helligkeit 99

\x00\x00\x02\x01\x2d\x00\x00\x00\x00\x02\x39\x39

LED Helligkeit auf 99%

LED Helligkeit 100

\x00\x00\x02\x01\x2d\x00\x00\x04\x00\x03\x31\x30\x30

LED Helligkeit auf 100%

Volume 0

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x30\x30

Lautstärke auf 0% (aus)

Volume 1

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x30\x31

Lautstärke auf 1%

Volume 2

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x30\x32

Lautstärke auf 2%

...

weitere Volume Einstellungen in Vorlage (*.xml) vorhanden...

...

Volume 10

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x31\x30

Lautstärke auf 10%

Volume 11

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x31\x31

Lautstärke auf 11%

...

weitere Volume Einstellungen in Vorlage (*.xml) vorhanden...

...

Volume 99

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02\x39\x39

Lautstärke auf 99%

Volume 100

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x03\x31\x30\x30

Lautstärke auf 100%

Volume "v"

\x00\x00\x02\x00\x40\x00\x00\x00\x00\x02<v>

Die Lautstärke kann durch bspw. einem Schieberegler variable eingestellt werden.
Hierfür ist aber die Logik zu beachten

Die Befehle setzen sich aus Füll-Zeichen (irgendein ASCII Zeichen oder leeren Control Characters wie bspw. \x00), aus Control Characters (\x02 für "STX" = "Start of Text", mehr Details hier: https://en.wikipedia.org/wiki/C0_and_C1_control_codes) und der eigentlichen Anweisung (bspw. STOP, also \x53\x54\x4f\x50) zusammen.

Die "Control Codes" werden sehr wirr und eigentlich nicht für die dafür vorgesehenen Zwecke genutzt. Ein richtiges Muster oder einheitliches Vorgehen konnte ich leider nicht entdecken bei der Verwendung einiger Hex-Codes als Steuerzeichen. Also ist die Referenz auf die Control Codes vermutlich nicht zielführend.

Einrichtung in Loxone Config via virtuellem Ausgang (UDP)

Die Einrichtung in Loxone ist denkbar einfach und mit der hier verlinkten XML-Datei schnell erledigt: VO_LibratoneZipp.xml

Schritt-für-Schritt Anleitung:

  1. Die XML Datei herunterladen (VO steht für "Virtual Output") und lokal abspeichern.

  2. In der Loxone Config dann die xml-Datei importieren über "Virtuelle Ausgänge > Vordefinierte Geräte > Vorlage importieren..."


    Screenshot: Vorlage importieren in Loxone Config


  3. Dann die Daten des virtuellen Ausgangs noch entsprechend anpassen (Namen und IP Adresse ändern)


    Screenshot: Konfiguration des virtuellen Ausgangs

  4. Die Befehle können dann direkt genutzt werden. Bspw. mit einem Langzeitklick des Lichtschalters die Libratone Zipp Lautsprecher einschalten und mit verlassen des Raumes wieder in den Standby versetzen


    Screenshot: Nutzung als Radio in Loxone Config, Steuerung über Lichtschalter

Die Befehle können nach Belieben eingebaut und genutzt werden.

Statusinformationen abrufen

Theoretisch kann man ein paar Statusinformationen der Libratone Boxen abrufen, allerdings nicht so komfortabel und der Mehrwert der Informationen hält sich auch in Grenzen. Ich habe deshalb nur mal die Möglichkeiten gesammelt und liste diese hier auf:

  • Via HTTP (Webseite): http://192.168.xxx.xxx/cgi?Overview (IP Adresse des Lautsprechers bitte entsprechend anpassen)

  • Via HTTP Port 49152 (XML): http://192.168.xxx.xxx:49152/description.xml (IP Adresse des Lautsprechers bitte entsprechend anpassen)

  • Via UDP Broadcast Paketen auf Port 1800: 
    NOTIFY * HTTP/1.1
    HOST: 239.255.255.250:1800
    PROTOCOL: Version 1.0
    NTS: ssdp-alive
    DeviceName: ZIPPTWOGREY_xxx
    DeviceID: xxx
    DeviceState: F,S,P
    PORT: 7777
    ZoneID: LINK ZippMiniOne_xxx 
    Creator:
    IPAddr: 192.168.xxx.xxx 
    ColorCode: 2010
    FWVersion: 1508;4450,;400,
    StereoPairID:
    ProVersion: 3.0,3.0
    DeviceType: 310
    AiMicStatus: 1
    Characterstic: 2,100,0,15,7,0,DE,de
    WifiInfo: ,-59,51/70 ,-62,48/70 ,-54,56/70 ,-54,56/70 ,-58,52/70
    VolSync: N

Nutzungsszenarien der Ausgänge in der Loxone Config

Hier ein paar Beispiele zur Einbindung bzw. Nutzung der Befehle.

  • Nutzung als "automatisches" Radio im Raum: Dazu muss sich die Box am Strom und im Standby befinden. Der Ausgangsbefehl "Favorit 1" reicht völlig aus, um die Box aus dem Standby zu holen und den Radio-Stream von Favorit 1 direkt zu starten. Beim Verlassen des Raumes kann ein Präsenzmelder oder das Ausschalten des Lichts genutzt werden, um den Lautsprecher wieder in den Standby zu setzen.


    Screenshot: Nutzung als Radio in Loxone Config, Steuerung über Lichtschalter


  • Nutzung zum Einschlafen: Dazu kann der eingebaute Standby Timer genutzt werden. Hierzu einfach die gewünschte Dauer als Befehl senden, dann schaltet sich die Box automatisch nach Ablauf der Zeit in den Standby. Kombinieren könnte man das natürlich auch mit dem Betriebsmodus "Schlafen", falls das genutzt wird. Dann geht der Timer automatisch auf 15 oder 30 Minuten des Lautsprechers im Schlafzimmer.


    Screenshot: Standby Timer in Loxone Config


  • Nutzung als Wecker: Auch hier könnte man automatisch den Lautsprecher aus dem Standby holen und zum Wecken nutzen. Im Beispiel wird durch den Wecker in Loxone der Favorit 2 gestartet.


    Screenshot: Wecker in Loxone Config


  • Lautstärke über Slider in Loxone: Hierfür kann man einen virtuellen Ausgang des Typs "Schieber" verwenden. Die variablen Ausgänge "Volume V einstellig", "Volume V zweistellig" und "Volume V dreistellig" können dafür genutzt werden. Die Hex-Codes sind leider verschieden für die einstelligen Lautstärken (0-9), sowie zweistelligen Lautstärken (10-99) und der dreistelligen Lautstärke (100). Mir ist noch keine elegantere Lösung eingefallen, die verschiedenen Ausgänge bei verschiedenen Zahlen zu verwenden, da Loxone leider keine Zahlen mit führenden Nullen erzeugen kann. Daher hier mal zwei funktionale Lösungsansätze.

    1. Nutzung aller drei variablen Volume Ausgänge mit einem Schieberegler. Die "falsch" erzeugten UDP Paket werden zwar versendet, allerdings vom Lautsprecher verworfen. Somit kommen immer zwei falsche und ein richtiges Paket beim Lautsprecher an. Alternativ kann bei diesem Ansatz aber der dreistellige Ausgang auch ignoriert und nicht verwendet werden, dann wäre es nur ein falsches Paket das immer mitgesendet werden würde.


      Screenshot: Nutzung aller drei variablen Volume Ausgänge mit einem Schieberegler

    2. Nutzung von MinMax Begrenzern und die 100 einfach weglassen (wird vermutlich sowieso nie verwendet, ist mega laut)

Multiroom Konfiguration

In der Libratone App lassen sich die WLan Lautsprecher per Drag&Drop miteinander zu einem sogenannten "Link" verbinden. Danach läuft auf beiden Boxen derselbe Stream.


Screenshot der Libratone App mit zwei verbundenen Lautsprechern.

Beispielhaft habe ich einen Zipp Mini und eine Zipp 2 Box zu einem Link verknüpft (siehe Screenshot). Hier möchte ich kurz die Szenarien beschreiben, auch hinsichtlich der Befehle oben und wie sich die Boxen dann verhalten:

  • Streamänderung: Wenn man bspw. statt Favorit 1, lieber Favorit 3 hören möchte, kann man das an eine beliebige Box innerhalb des Links schicken. Die jeweils andere(n) Box(en) innerhalb des Links werden dann automatisch mit angepasst.

  • Lautstärkeänderung: Die Lautstärke ist immer noch pro Box separat einstellbar.

  • Lautsprecher einzeln ein-/ausschalten: Der Link bleibt bestehen, auch wenn eine einzelne Box vorrübergehend oder dauerhaft ausgeschalten wird. Sofern man dann eine im Link enthaltene Box wieder einschaltet, so wird diese automatisch von den anderen Boxen "informiert" und passt sich sofort wieder in den Link ein und startet den entsprechenden Stream automatisch.

Testen via PowerShell

Wer gerne selbst etwas testen möchte und sich mit weiteren Funktionen auseinandersetzen möchte, kann das auch ohne Loxone tun. Ich selbst habe zum Testen und Forschen ein PowerShell Script erstellt und genutzt. Nachfolgend das Script mit ein paar Byte Arrays als Test. Mit der Funktion [System.Text.Encoding]::ASCII.GetString($byteArray) kann der Hex-Code auch in ein ASCII String konvertiert werden, wobei hierbei nicht alle benötigten Zeichen angezeigt werden können (bspw. die Steuerzeichen).

Libratone Command Script
function Send-LibratoneCommand { param ( [string]$toIP = "192.168.xxx.xxx", [int]$toUDPPort = 7777, [int]$fromUDPPort = 58800, $send = "" ) $IP = [System.Net.Dns]::GetHostAddresses($toIP) $Address = [System.Net.IPAddress]::Parse($IP) $EndPoints = New-Object System.Net.IPEndPoint($Address, $toUDPPort) $Socket = New-Object System.Net.Sockets.UDPClient($fromUDPPort) $SendMessage = $Socket.Send($send, $send.count, $EndPoints) $Socket.Close() } # Favorites #...{"isFromChannel":false,"play_identity":"1","play_subtitle":"1","play_title":"channel","play_type":"channel","token":""} [Byte[]] $favorites1 = 0xaa, 0xaa, 0x02, 0x01, 0x15, 0x00, 0x1f, 0xdb, 0x00, 0x77, 0x7b, 0x22, 0x69, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3a, 0x22, 0x22, 0x7d #...{"isFromChannel":false,"play_identity":"2","play_subtitle":"2","play_title":"channel","play_type":"channel","token":""} [Byte[]] $favorites2 = 0xaa, 0xaa, 0x02, 0x01, 0x15, 0x00, 0xb7, 0xa2, 0x00, 0x77, 0x7b, 0x22, 0x69, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x32, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x32, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x3a, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3a, 0x22, 0x22, 0x7d # Volume [Byte[]] $volume11 = 0xaa, 0xaa, 0x02, 0x00, 0x40, 0x00, 0x6e, 0x61, 0x00, 0x02, 0x31, 0x31 [Byte[]] $volume12 = 0xaa, 0xaa, 0x02, 0x00, 0x40, 0x00, 0x6e, 0x61, 0x00, 0x02, 0x31, 0x32 [Byte[]] $volume13 = 0xaa, 0xaa, 0x02, 0x00, 0x40, 0x00, 0x6e, 0x61, 0x00, 0x02, 0x31, 0x33 [Byte[]] $volume23 = 0xaa, 0xaa, 0x02, 0x00, 0x40, 0x00, 0x6e, 0x61, 0x00, 0x02, 0x32, 0x33 # Pause/Stop Streaming [Byte[]] $stop = 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x53, 0x54, 0x4f, 0x50 [Byte[]] $play = 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x04, 0x50, 0x4c, 0x41, 0x59 # Sending commands to test Send-LibratoneCommand -toIP "192.168.xxx.xxx" -toUDPPort 7777 -fromUDPPort 58800 -send $favorites1 Send-LibratoneCommand -toIP "192.168.xxx.xxx" -toUDPPort 7777 -fromUDPPort 58800 -send $favorites2 Send-LibratoneCommand -toIP "192.168.xxx.xxx" -toUDPPort 7777 -fromUDPPort 58800 -send $volume12 Send-LibratoneCommand -toIP "192.168.xxx.xxx" -toUDPPort 7777 -fromUDPPort 58800 -send $stop Send-LibratoneCommand -toIP "192.168.xxx.xxx" -toUDPPort 7777 -fromUDPPort 58800 -send $play # Convert Byte Arrays to ASCII String to find out more information [System.Text.Encoding]::ASCII.GetString($favorites1) [System.Text.Encoding]::ASCII.GetString($favorites2) [System.Text.Encoding]::ASCII.GetString($stop)