Sonos Control Szene (mit Sonos-HTTP-API)

Advertisements

Mit der Sonos-HTTP-API gelingt die Smart Home Integration der beliegbten Sonos Player schon nahezu perfekt. Um die Nutzung noch ein wenig smarter zu machen findest Du in diesem Artikel die Sonos Control Szene um automatische Gruppierungen zu realisieren.

Sonos Control Szene

Sonos Control Szene

Mein Sonos Setup

In meinem Smart Home gibt es insgesamt vier Lautsprecher aus dem Hause Sonos. In Küche und Schlafzimmer spielt jeweils ein Play:1, im Badezimmer unterhält ein Play:3 und die Hifi-Anlage im Wohnzimmer wird durch einen Sonos:Connect vervollständigt. Alle Geräte werden über die Sonos-HTTP-API mit entsprechendem virtuellen Device gesteuert. Im Badezimmer und der Küche habe ich die Lautsprecher mit der Lichtszene gekoppelt, so dass beim Betreten eine eigene Playlist, bzw. der Lieblingssender gespielt wird. Soweit so gut.

Meine Sonos Geräte waren jedoch bisher weitestgehend Einzelgänger und wurden allenfalls mal per Sonos App zu einer Gruppe zusammengefasst. Jedes der Geräte hat also eine eigene Verbindung zur Audioquelle und gibt die Inhalte wieder. Der tolle Klang der Geräte und deren Nutzung macht Spaß, aber einer der größten Stärken des Systems habe ich bisher viel zu wenig Aufmerksamkeit geschenkt. Der Multiroom-Wiedergabe., also der synchronen Wiedergabe einer Audio-Quelle in mehreren Räumen oder gar dem ganzen Haus.

Auch wenn in Küche und Badezimmer immer derselbe Radiosender gespielt wird, ist die Wiedergabe nie synchron. Eigentlich kein Problem, aber die Räume sind relativ dicht nebeneinander. Hast Du schon mal zwei oder mehr Lautsprechern gehört, welche dieselbe Audioquelle mit einem kleinen Versatz wiedergeben? Das klingt grauenhaft und verdirbt den Spaß. Die nachfolgende Szene sorgt hier Abhilfe.

Sonos Control Szene

Die Sonos Control Szene ermöglicht die vollautomatische Sonos Gruppierung in Deinem Smart Home. Beim Start eines Players durch die Szene (Trigger im Header) wird der Zustand aller konfigurierten Player geprüft. Läuft auf einem anderen Player bereits eine Wiedergabe, erfolgt automatisch eine Gruppierung und die Audioquelle des ersten Players wird übernommen. Beim Beenden eines der Trigger wird der betreffende Player automatisch wieder aus der Gruppe entfernt.

Beispiel Szenario (1): Lichtszene

Wie oben beschrieben, sind meine Sonos Player mit den Lichtszenen in Küche und Badezimmer gekoppelt. Beim Betreten meiner Küche wird die ausgewählte Playlist auf dem Play:1 gestartet. Gehe ich nun bei laufender Wiedergabe ins Badezimmer, übernimmt der dortige Play:3 automatisch die Wiedergabe aus der Küche. Die beiden Player laufen synchron mit derselben Audioquelle. Wenn der Timer für die Lichtszene in der Küche abläuft, wird das Licht ausgeschaltet und der Sonos Player aus der Küche aus der Gruppe entfernt. Im Badezimmer jedoch wird die Wiedergabe fortgesetzt.

Sonos Control Szene im HC2

Sonos Control Szene im HC2

Beispiel Szenario (2): TV Ton im ganzen Haus

Neben der Wiedergabe von Audioinhalten über den A/V-Receiver dient der Sonos:Connect im Wohnzimmer zur Einspeisung von Audiosignalen in das Sonos-System. Ich kann also den Ton meiner Hifi-Geräte auf jedem meiner Sonos Player wiedergeben. Dabei verhält sich der Sonos:Connect wie ein normaler Player und kann somit problemlos mit der Sonos Control Szene genutzt werden. Wenn also mein Fernseher läuft und einer der Szenen-Trigger auslöst, erfolgt die Übertragung der Fernsehtons über den Sonos:Connect auf den jeweiligen Player.

Features / Konfiguration

Die Sonos Control Szene bietet eine ganze Reihe von Konfigurationsmöglichkeiten:

  • Tageszeitabhängig kannst Du:
    • Sonos Player in die Steuerung einfügen
    • Festlegen von welchen Geräten laufende Audioquellen übernommen werden
    • Lautstärke und Bassintensität einstellen
    • Playlist / Sender / Titel je Raum definieren

Du musst also in der Küche nicht automatisch die Musik aus dem Kinderzimmer hören und weckst nachts nicht das ganze Haus, sobald Du einen Raum betrittst.

Systemanforderungen

  • Mindestens einen Sonos Player (egal welche(r))
  • Installierte und konfigurierte Sonos-HTTP-API (ab Version 1.6.6)
  • Die Namen der Sonos Player müssen identisch zu den Namen der Räume im Home Center sein
  • In der Sonos App muss mindestens ein Objekt unter „Mein Sonos“ angelegt sein

Bekannte „Schönheitsfehler“

  1. Wird bei aktiver Gruppierung die Wiedergabe an einem der Player manuell – also am Gerät, per App oder virtuell Device – beendet, stoppt die Wiedergabe auf allen Geräten der Gruppe.
  2. Der zuerst gestartete Player ist im Sonos System der Master einer Wiedergabe. Wird dieser durch den Szenentrigger ausgeschaltet – also aus der Gruppe entfernt – muss ein neuer Master bestimmt werden. Dies übernimmt die Sonos-HTTP-API automatisch, jedoch wird die Wiedergabe aller Gruppenmitglieder ganz kurz gestoppt.

Konfiguration der Sonos Control Szene

Szenen Trigger

--[[
%% properties
75 value
91 value
%% events
%% globals
--]]

Im Header der Sonos Control Szene müssen die Geräte eingetragen werden welche für die Dauer der Wiedergabe einen Parameter Value mit dem Wert > 0 haben. Dies sind beispielsweise alle WallPlugs, Switches und Dimmer. Hier musst Du  alle Geräte eintragen, welche Du zum automatischen Start der Szene nutzen möchtest. Bei mir sind dies jeweils Lichtquellen in Badezimmer und Küche. Manuell zu berücksichtigende Player – wie bei mir der Sonos:Connect im Wohnzimmer – benötigen keinen Trigger.

Die Sonos Control Szene wertet automatisch aus, in welchem Raum sich das Gerät befindet und sucht einen Sonos Player mit selbigem Namen wie der Raum.

Grundeinstellungen

---------------------------------------------------
---------- Einstellungen --------------------------
varDebug 			= true 					-- Debug logs true oder false
sonosAPI			= '10.10.10.3:5005'			-- Adresse der Sonos-HTTP-API
  • varDebug: Erweiterte Debug Informationen im Home Center 2 true/false
  • sonosAPI: IP Adresse und Port der Sonos-HTTP-API

Mapping der globalen Variablen

Hier musst Du nichts verändern, wenn Du die gängigen globalen Variablen verwendest.

---------------------------------------------------
---------- gVar Mapping ---------------------------
sleepState   		= "SleepState"; 
timeOfDay    		= "TimeOfDay"; 
presentState 		= "PresentState"; 
sleepStateMapping       = {Sleeping="Sleeping", Awake="Awake"};
timeOfDayMapping        = {Morning="Morning", Day="Day", Evening="Evening", Night="Night"};
presentStateMapping     = {Home="Home", Away="Away", Holiday="Holiday"};

playConfig

Die Konfiguration der Sonos Player nach Tageszeit und mit erweiterten Parametern.

---------------------------------------------------
---------- playConfig -----------------------------
sonosSleeping = {}; 
sonosMorning  = {{room='bad', volume=12, favorite="NDR%202", shuffle="on", bass=0}, {room='kueche', volume=12, favorite="NDR%202", shuffle="on", bass=0}, {room='wohnzimmer', volume=12, favorite="NDR%202", shuffle="on", bass=0}};
sonosDay      = {{room='bad', volume=12, favorite="NDR%202", shuffle="on", bass=0}, {room='kueche', volume=12, favorite="NDR%202", shuffle="on", bass=0}, {room='wohnzimmer', volume=12, favorite="NDR%202", shuffle="on", bass=0}};
sonosEvening  = {{room='bad', volume=12, favorite="NDR%202", shuffle="on", bass=3}, {room='kueche', volume=12, favorite="NDR%202", shuffle="on", bass=3}, {room='wohnzimmer', volume=12, favorite="NDR%202", shuffle="on", bass=3}};
sonosNight    = {{room='bad', volume=12, favorite="NDR%202", shuffle="on", bass=-5}, {room='kueche', volume=12, favorite="NDR%202", shuffle="on", bass=-5}, {room='wohnzimmer', volume=12, favorite="NDR%202", shuffle="on", bass=-5}};

Für jeden Status der globalen Variable TimeOfDay musst Du ein Array definieren (sonosMorning, sonosDay, etc.). Innerhalb dieses Arrays musst Du wiederum ein Array für jeden zu inkludierenden Player/Raum und allen Einstellungen erstellt.

Beispiel:

sonosMorning  = {{room='bad', volume=12, favorite="Charts%20Deutschland", shuffle="on", bass=0}};

Hier wird für die Tageszeit Morning der Player im Raum „bad“ mit der Lautstärke 12, der Playlist „Charts Deutschland“ im Shuffle Modus und neutraler Bass-Einstellung berücksichtigt.

Die Parameter im Einzelnen:

  • room: Entspricht dem Raumnamen im Home Center sowie dem Namen des dazugehörigen Sonos Players
  • volume: Lautstärke der Wiedergabe (0-100)
  • favorite: Exakter Titel des wiederzugebenden Objektes aus „Mein Sonos“ der Sonos App (Leerzeichen sind hier mit %20 zu ersetzen)
  • shuffle: Wiedergabe von Playlisten im Shuffle-Modus (Zufallsreihenfolge) on/off
  • bass: Sonos Bass-Level -10 bis 10

extraPlayCheck

Manchmal ist es sinnvoll, dynamisch einzelne Player aus der Konfiguration ausschließen zu können oder überhaupt keine Wiedergabe zu starten. Dies kannst Du mit der Funktion extraPlayCheck realisieren. Dafür musst Du lediglich den Rückgabewert der Funktion anpassen.

Beispiel 1: Alle Player sollen stumm bleiben

Um keinen Deiner Player zu starten muss die Funktion den Wert true zurück liefern. Wenn beispielsweise die globale Variable Darkness auf 0 steht, soll in keinem Raum Musik wiedergegeben werden. Der Code dafür sieht folgendermaßen aus:

---------------------------------------------------
--------- extraCheck ------------------------------
function extraPlayCheck() 

  if fibaro:getGlobalValue('Darkness') == '0' then 
    return true 
  else
    return false
  end

end

Beispiel 2: In der Küche soll keine Wiedergabe gestartet werden, wenn der Fernsehen läuft

Um einzelne Player aus der Konfiguration auszuschließen muss die Funktion ein Array zurück liefern. In diesem Array listest Du alle Player auf, die beim triggern der Szene nicht gestartet werden sollen.

---------------------------------------------------
--------- extraCheck ------------------------------
function extraPlayCheck() 

    if tonumber(fibaro:getValue(35, "power")) > 30 then
      removePlayer = {'kueche'}
      return removePlayer
    else
      return false
    end
end

 

ChangeLog

  • 1.0: Initiale Version
  • 1.1: Bugfixing: Raum- und Playernamen angepasst
  • 1.2: ExtraPlayCheck Funktion ergänzt

Download

Die Sonos Control Szene wird kostenfrei zur Verfügung gestellt und darf für den eigenen Gebrauch modifiziert werden. Die Weiterverbreitung – auch in Teilen oder modifiziert – ist ausschließlich unter Nennung des Autors gestattet.

Bildquellen

  • Sonos Control Szene: Bastian
  • Sonos Control Szene im HC2: Bastian
Posted in Sonos and tagged , , .

8 Comments

  1. Hallo Bastian,
    klasse Idee mit der automatischen Gruppierung.
    Hier noch ein kleiner Verbesserungsvorschlag (oder Wunsch):
    Ich habe meine Lichtszenen so konfiguriert, dass tagsüber das Licht beim Betreten eines Raumes nicht angeht. Dadurch funktioniert das Licht als Trigger nicht.
    Man müsste also doch den Bewegungsmelder abfragen. Oder in den Lichtszenen mit einer zusätzlichen Variablen arbeiten, welche dann als Trigger dienen.
    Vielleicht kann man als Trigger auch den SonosStatus der SONOS-Player selbst verwenden.
    Gruß
    Jeff

    • Moin Jeff,

      guter Punkt den ich auch erwartet habe.
      Leider habe ich noch keine schlanke Möglichkeit gefunden dies zu realisieren. Wie meinst Du das mit dem Sonos Status als Trigger?

      Die einzig tragbare Möglichkeit wäre ein Timer der die Geräte nach einer gewissen Zeit ohne Bewegung wieder aud der Gruppe entfernt. Dies zieht wiederum andere Dinge nach sich die eine Realisierung erschweren. Solange es hell genug ist und die Lichtszene nicht mit auslöst ist es okay, aber wenn beides angeht, dann sollte es auch – passend zum Thema – synchron passieren.
      Ich bin an dem Thema also noch dran und zuversichtlich, dass hier noch ein Update kommen wird. Euren Input und Eure Ideen nehme ich natürlich gern mit.

      Grüße
      Bastian

  2. Hallo Bastian,
    ich speichere den Status der Sonos-Lautsprecher in einer Variablen:
    fibaro:setGlobal(„sonosWohnState“, zonestate)
    fibaro:setGlobal(„sonosSchlafState“, zonestate)

    Die ganze primäre Schleife sieht so aus:
    local device = fibaro:getSelfId();
    local zonename = fibaro:getName(device);
    local ipaddress = fibaro:getValue(device, „IPAddress“);
    local port = fibaro:getValue(device, „TCPPort“);
    sonos = Net.FHttp(ipaddress, port);
    response = sonos:GET(„/“.. zonename .. „/state“)
    fibaro:debug(response)
    jsonTable = json.decode(response);
    local zonestate = jsonTable.playbackState;
    local zonetitle = jsonTable.currentTrack.title;
    local zonevolume = jsonTable.volume;
    fibaro:call(device,“setProperty“,“ui.lblState.value“,zonestate);
    fibaro:call(device,“setProperty“,“ui.lblTitle.value“,zonetitle);
    fibaro:call(device,“setProperty“,“ui.lblVol.value“,zonevolume);
    fibaro:call(device, „setProperty“, „currentIcon“, 23)
    — ab hier neu + test
    fibaro:setGlobal(„sonosWohnState“, zonestate) — neu 22.11.18
    — Schlafzimmer‘:
    response = sonos:GET(„/“.. „Schlafzimmer“ .. „/state“)
    fibaro:debug(response)
    jsonTable = json.decode(response);
    local zonestate = jsonTable.playbackState;
    fibaro:setGlobal(„sonosSchlafState“, zonestate)
    —————

    In der primären Schleife vom Sonos-VD (ich glaube von deinem).
    Die Variablen könnten als trigger für deine Szene dienen. Damit würde auch das manuelle Einschalten am Sonos erkannt werden.
    Gruß
    Jeff

    • Moin Jeff,

      danke für die Anregung. Die Schleifen in den VDs laufen mir einfach nicht zuverlässig genug um diese ernsthaft zu verwenden, aber die Idee gefällt mir grundsätzlich.
      Den manuellen Start eines Players zu erkennen hilft in diesem Szenario aber nicht weiter, oder bin ich auf dem gedanklich Holzweg?

      Nebenbei: Ist nicht mein VD 😉 Will mich ja nicht mit fremden Federn schmücken.

      Grüße
      Bastian

  3. Hi,
    habe etwas mit deiner Szene gespielt.
    Zunächst brachte er immer folgende Fehlermeldung:
    DEBUG] 16:09:05: Keine playConfig gefunden. Szene beendet
    Nachdem ich dann folgende Zeilen ersetzt habe ging es:
    if value.room == string.lower(val) then
    ersetzt durch
    if value.room == val then
    und
    if value.room == string.lower(val) then
    ersetzt durch:
    if value.room == val then
    (Also string.lower weg. Meine Player heißen „Bad“ und nicht „bad“.)

    Nun kommt immer noch folgende Fehlermeldung, aber es scheint trotzdem zu gehen:
    [DEBUG] 15:15:32: 2019-01-05 15:15:32.124219 [ fatal] LUA error: /opt/fibaro/scenes/39.lua:167: attempt to index global 'playConfigRoom' (a nil value)

    in folgender Zeile:
    getMethod('http://'..sonosAPI..'/'..sDevState[i][1]..'/volume/'..playConfigRoom.volume

    Und falls es dich interessiert:
    Ich habe noch folgende Trigger eingefügt:
    sonosBadState
    sonosSchlafState
    und ganz am Ende vor dem else folgende Zeilen eingefügt:
    elseif t.type == 'global' and t.name == "sonosSchlafState" then
    debug('red','Szene getriggert im Raum Schlafzimmer durch sonosSchlafState! Suche Sonos Lautsprecher...')
    getPlayConfig()
    local vschlaf = "1"
    if fibaro:getGlobal("sonosSchlafState") == "STOPPED" then vschlaf = "0"; end
    getSonosZones("Schlafzimmer", vschlaf , playConfig)
    elseif t.type == 'global' and t.name == "sonosBadState" then
    debug('red','Szene getriggert im Raum Bad durch sonosBadState! Suche Sonos Lautsprecher...')
    getPlayConfig()
    local vbad = "1"
    if fibaro:getGlobal("sonosBadState") == "STOPPED" then vbad = "0"; end
    --fibaro:debug("->" .. "Bad" .. " / " .. vbad )
    getSonosZones("Bad", vbad , playConfig)

    Kannst ja mal drüberschauen wenn du Zeit und Lust hast.
    Gruß
    Jeff

    • Hi Jeff,

      das mit dem string.lower war noch ein Bug. Habe ich in der Version 1.1 angepasst.

      Deine Anpassungen kann ich zwar nachvollziehen, aber sie sind schon sehr speziell auf Deine Bedürfnisse zugeschnitten und topedieren den eigentlichen Zweck der Automatisierung.
      Abgesehen davon bin ich kein Freund von globalen Variablen um aktive Szenen zu steuern, aber wenn es für Dich passe, wunderbar.

      Grüße
      Bastian

  4. Hi Bastian,

    danke für die tolle Control Szene! Das wird meine Szenen viel übersichtlicher machen. Aktuell habe ich nur ein Problem. Ich habe Wohnzimmer und Küche offen, das Problem ist jetzt wenn ich den TV an habe und in die Küche gehe das dort die Musik anfängt zu spielen. Aktuell habe ich dies über den Stromverbrauch vom Wallplug geregelt, er erkennt das die der TV eingeschaltet ist (verbrauch über 30 Watt) und startet somit nur die Indirekte beleuchtung und nicht die Musik. Hast du eine Idee wie ich dies mit Integrieren kann?

    Lg. Tobias

    • Hallo Tobias,

      danke für Deine Anmerkung. Freut mich, dass die Szene hilft.
      Dein Problem ist mir auch schon untergekommen, daher sitze ich schon an einer erweiterten Version der Szene um genau dies zu bewerkstelligen.
      Wenn alles klappt und die Tests erfolgreich verlaufen, dann gibt es kurzfristig ein Update.

      Grüße
      Bastian

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Ich akzeptiere