Sonos2mqtt - vielleicht hat jemand Lust mitzumachen

Begonnen von Otto123, 31 Mai 2020, 18:30:55

Vorheriges Thema - Nächstes Thema

Ralli

#1035
Hallo Otto,

vielen Dank für Deine Unterstützung.
Zitat von: Otto123 am 24 Mai 2021, 22:48:43
was funktioniert ist: ein publish in der Art
sonos/cmd/setalarm {"ID":73,"Enabled":true}

Ich kann bestätigen, dass das funktioniert, um einen Alarm zu modifizieren ohne die anderen vorhandenen Alarme zu löschen oder zu verändern.

Es klappt auch folgendes, um mehrere Einstellungen eines Alarms zu verändern:


set MQTT2_SonosServer publish sonos/cmd/setalarm {"Duration":"01:00:00","Enabled":true,"ID":11417,"IncludeLinkedZones":false,"PlayMode":"SHUFFLE",\
"ProgramMetaData":{"Title":"SWR3 99.6 (Top 40/Pop)","UpnpClass":"object.item.audioItem.audioBroadcast","ItemId":"R:0/0/31","ParentId":"R:0/0"},\
"ProgramURI":"x-sonosapi-stream:s24896?sid=254&flags=8224&sn=0",\
"Recurrence":"ON_1","StartLocalTime":"05:30:00","Volume":15}


Damit kann ich jetzt schon einmal weiter arbeiten.
Gruß,
Ralli

Proxmox 8.1 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.3 dev, virtualisierte RaspberryMatic (3.75.6.20240316) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.1.5) und HMW-GW, FRITZBOX 7490 (07.57), FBDECT, Siri und Alexa

Otto123

Moin Ralli,

du wolltest ja sowas:
set Sonosbox Alarm Enable All
set Sonosbox Alarm Disable All

Da müsste man jetzt eventuell "einfach" das json Array aus listalarm, "Enabled":true gegen das "Gegenteil" austauschen (also aus true false machen bzw. umgekehrt) und mit setalarm zurückschreiben.
Leider nimmt er bei setalarm offenbar nicht einfach das array [vier Alarme] sondern nur den einzelnen Alarm. Da müsste man jetzt zerlegen und alle einzelnen senden. :-[

Nur mal mein erster Ansatz für die FHEM Kommandozeile
{my $s=ReadingsVal('SonosBridge','alarms','');;$s=~s/"Enabled":true/"Enabled":false/g;;return $s}

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Otto123

Hallo Karsten,

Zitat von: hydrotec am 25 Mai 2021, 06:13:40
Docker wollte ich mir eigentlich nicht auch noch antun.  ;)
Ob das nicht das geringere Übel ist? Den nodejs Kram finde ich auch schwer beherrschbar.
Aus meiner Erinnerung mit sonos2mqtt:
sudo npm install -g sonos2mqtt
node /usr/lib/node_modules/sonos2mqtt --version

Man beachte: als user mit sudo "global" installiert, dann aber als normaler user zum Test mal gestartet! Mal analog mit sonsos-tts-polly probieren?

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Ralli

Moin Otto,

Zitat von: Otto123 am 25 Mai 2021, 09:11:06
Nur mal mein erster Ansatz für die FHEM Kommandozeile
{my $s=ReadingsVal('SonosBridge','alarms','');;$s=~s/"Enabled":true/"Enabled":false/g;;return $s}

vielen Dank.

Ich denke, ich werde die utils etwas erweitern. Dein Ansatz ist gut, wirkt aber dann tatsächlich auf ALLE Alarme ALLER Boxen. Ich brauche aber eine Steuerung pro Box. Ich bin schon am Experimentieren :-).
Gruß,
Ralli

Proxmox 8.1 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.3 dev, virtualisierte RaspberryMatic (3.75.6.20240316) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.1.5) und HMW-GW, FRITZBOX 7490 (07.57), FBDECT, Siri und Alexa

Otto123

Dann schau Dir in der Utils die sub sonos2mqtt_searchList, dort behandle ich die kompletten json der Favoriten und Playlisten usw.
Wenn Du das pro Box machen willst musst Du ja den Alarm anhand der "RoomUUID" der Box zuordnen. Primär brauchst Du dann ja die ID - aber mit der will man ja in der UI nicht arbeiten. :D
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Ralli

Hallo Otto,

ich habe folgendes vor:

1) Ich baue eine Funktion in die Utils ein, um über die Bridge die Liste der Alarme zu holen und dort in das Reading Alarms zu speichern und dann im Anschluss die Alarme in den entsprechenden Speakern in den Readings "Alarms" und "AlarmIDs" einzutragen.
2) Dann erweitere ich in den Utils die entsprechende(n) Funktion(en), um für die Speaker zunächst einmal nur das Kommando "alarm <(ID|all)> <(enable|disable)>" abzubilden. Wahrscheinlich werde ich dafür als Grundlage bereits "alarm <(ID|all)> <update> <"KEY":"Value" ...>" implementieren.

Wenn ich damit so weit bin, gebe ich dir den Code zum Review und ggf. Einbau.

Dann versuche ich mich noch dem Thema "AlarmRunning" als Reading zu nähern, damit bin ich nämlich noch nicht weitergekommen.
Gruß,
Ralli

Proxmox 8.1 Cluster mit HP ED800G2i7, Intel NUC11TNHi7+NUC7i5BNH, virtualisiertes fhem 6.3 dev, virtualisierte RaspberryMatic (3.75.6.20240316) mit HB-RF-ETH 1.3.0 / RPI-RF-MOD, HM-LAN-GW (1.1.5) und HMW-GW, FRITZBOX 7490 (07.57), FBDECT, Siri und Alexa

Otto123

Ich würde die Ergänzung der Bridge um die Alarme zu holen in die Utils einbauen:
sub sonos2mqtt_setup
....
   sonos2mqtt_mod_list($devspec,'readingList',AttrVal($devspec,"devicetopic",'sonos').'/alarms:.* alarms');
   sonos2mqtt_mod_list($devspec,'getList','listalarms:noArg alarms sonos/cmd/listalarm');
...

Zum Probieren in der FHEM Kommandozeile.
   {my $devspec='SonosBridge';;   sonos2mqtt_mod_list($devspec,'readingList',AttrVal($devspec,"devicetopic",'sonos').'/alarms:.* alarms');;   sonos2mqtt_mod_list($devspec,'getList','listalarms:noArg alarms sonos/cmd/listalarm')}
Damit muss ich das Template nicht ändern und habe den Code an einer Stelle.

Wegen dem AlarmRunning Reading musst Du mal am Anfang des Threads schauen, da war es schon mal da. Notfalls muss man mal noch so ein "Urdevice" bauen :)
Tipp: geh hier im Thread auf "drucken" und dann mit ctrl+f nach AlarmRunning suchen.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

hydrotec

@Otto

Grundinstallation ist wie bei sonos2mqtt, welches einwandfrei funktioniert.


Nur mal auf die Schnelle versucht.

Eingabe:

sudo npm i -g @svrooij/sonos-tts-polly

Ergebnis:

changed 83 packages, and audited 84 packages in 4s

3 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities


Eingabe:

node /usr/lib/node_modules/sonos-tts-polly --version

Ergebnis:

internal/modules/cjs/loader.js:888
  throw err;
  ^

Error: Cannot find module '/usr/lib/node_modules/sonos-tts-polly'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15)
    at Function.Module._load (internal/modules/cjs/loader.js:730:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}


Es fehlen also noch einige Sachen für die Erweiterung.
Werde ich mal in Ruhe ausklamüsern.

Gruß, Karsten

Otto123

#1043
Ich sage ja, das nodejs ist auch nicht die logischste Lösung ... :)

Offenbar ist der Eintrag im Repository anders (ohne @svrooij wird es nicht gefunden) damit @svrooij/ wird aber auch der Installpfad verändert.

Versuch mal  :-X :-*
node /usr/lib/node_modules/@svrooij/sonos-tts-polly --version
Und dann vielleicht auch den testweisen Aufruf mit den Parametern so machen?
Final dann den Start mit pm2 wie ich das mal für sonos2mqtt beschrieben habe?

BTW: Der Aufruf aus #1008, den Sebastian dort mal vorgelegt hatte, geht nach meiner Überlegung wahrscheinlich gar nicht, oder maximal in einer Umgebung wo irgendwie alles auf node ausgerichtet ist :)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

LordVoodoo

#1044
Hallo,

ich bin ein bisschen weitergekommen und habe nochmal folgendes gemacht:


  • Alle Geräte in FHEM neu aufgebaut.
  • Alle Favoriten in SONOS gelöscht und nur zwei Einträge angelegt.

Der Befehl für den Radiosender FFH Soundtrack funktioniert:
set Dev_Schlafzimmer_Soundbar playUri x-sonosapi-stream:tunein:20753?sid=303&flags=8224&sn=1

Für das gespeichertes TIDAL-Album "The Greatest Video Game Music" klappt es nicht:
set Dev_Schlafzimmer_Soundbar playUri x-rincon-cpcontainer:1004206calbum%2f97375617?sid=174&flags=8300&sn=2

{"command":"setavtransporturi","error":{"Action":"SetAVTransportURI","FaultCode":"s:Client","Fault":"UPnPError","UpnpErrorCode":714,"UpnpErrorDescription":"Illegal MIME-Type","name":"SonosError"}}


Meine Vermutung war, dass das Sonderzeichen "/" den Fehler auslöst. Ich habe drei Varianten ausprobiert (Ersetzung durch \/, Ersetzung durch %2f und Ersetzung durch //), jedoch konnte ich das ganze nicht auflösen.

Wenn ich jedoch das genannte Album über die SONOS-App starte funktioniert das korrekte Auslesen der Informationen. Das Starten aus FHEM heraus ist das Problem.

Nutzt jemand TIDAL oder auch andere Streaming-Anbieter abseits von TuneIn / Radio, zur Steuerung?

eddy242

Hallo zusammen,

sonos2mqtt finde ich hervorragend und im Vergleich zum klassischen Sonos Modul gefühlt bei mir stabiler. Dieses Problem hatte ich allerdings auch:

Zitat von: Phiolin am 22 Mai 2021, 08:49:25
Was mir hauptsächlich aus dem "alten" Sonos Modul beim MQTT noch fehlt, ist die Möglichkeit vor einer Sprachausgabe noch einen Gong o.ä. abzuspielen. Im Sonos Modul konnte man ja immer praktisch beliebige zusätzliche MP3 files im speak einbinden. Da ich die Sonos Boxen hauptsächlich dafür benutze, fällt das schon auf. Es ist einfach etwas merkwürdig, wenn die Box einfach so zu sprechen anfängt ohne sich vorher durch Gedudel bemerkbar zu machen. :D
Ich vermute aber mal, das ist nicht so einfach zu implementieren?

Ich habe mal ein kleines DOIF geschrieben was je nach Durchsagenart verschiedene Jingles in verschiedener Lautstärke abspielt und die Sprachnachricht zusätzlich. Dann habe ich gleich noch die Transportoption TelegramBot dazu genommen (in diesem Board natürlich off-topic), ich konnte so den "msg" Befehl redundant machen. Da in einem Zimmer auch ein Echo Dot steht und der Sprachbefehl dort anders funktioniert, habe ich das über 2 Parameter im Stammdatensatz konfigurierbar gemacht. Die elsif's in der Hauptroutine muss man natürlich je nach Geschmack und Einsatzzweck umformen. Die Pausenzeiten (nach "sleep") sollten mindestens die Dauer des mp3's sein + 1-2 Sekunden Sicherheitspuffer.

FHEM, sonos2mqtt und sonostts laufen bei mir jeweils in Docker Containern, d.h. die URL des Ausgabegeräts muss natürlich individuell angepasst werden.
Noch ein kleiner Hinweis, wenn man sich im sonostts ein volume wie u.a. mappt, kann man auf dem Docker-Host die Jingle Daten bequemer abladen.

    volumes:
      - /data/container/Sprachausgabe:/usr/src/app/.cache


Aufruf mit
set messaging message (telegram|audio) <TargetDevice> <Warntype> <Nachricht>
Beispiel: set messaging message audio Wohnzimmer alert Es wird sehr windig!




defmod messaging DOIF subs  {\
    push (@{$_devicesraw},[("Bernhard","MQTT2_RINCON_7828CA6EF12A01400","speak de-DE Vicki","1","1")]);;\
    push (@{$_devicesraw},[("Julia","ECHO_G090U50784070X3Q","speak","0","0")]);;\
    push (@{$_devicesraw},[("Heiko","MQTT2_RINCON_B8E93720C12001400","speak de-DE Vicki","1","1")]);;\
    push (@{$_devicesraw},[("Wohnzimmer","MQTT2_RINCON_48A6B8D0DC3401400","speak de-DE Vicki","1","1")]);;\
    push (@{$_devicesraw},[("Anton","MQTT2_RINCON_7828CA6EF11201400","speak de-DE Vicki","1","1")]);;\
\
    for (my $i=0;; $i < @{$_devicesraw};; $i++) {\
        push (@{$_targets},$_devicesraw[$i][0]);;\
        $_devices{$_devicesraw[$i][0]}{device}    = $_devicesraw[$i][1];;\
        $_devices{$_devicesraw[$i][0]}{speakcmd}  = $_devicesraw[$i][2];;\
        $_devices{$_devicesraw[$i][0]}{addloud}   = $_devicesraw[$i][3];;\
        $_devices{$_devicesraw[$i][0]}{canjingle} = $_devicesraw[$i][4];;\
    }\
\
    push (@{$_warntypesraw},[("info","oldtimer.mp3","sleep 4;;","25")]);;\
    push (@{$_warntypesraw},[("warn","tos_bosun_whistle_1.mp3","sleep 4;;","25")]);;\
    push (@{$_warntypesraw},[("alert","tng_red_alert2.mp3","sleep 8;;","40")]);;\
    push (@{$_warntypesraw},[("sleep","lautes-schnarchen.mp3","sleep 5;;","25")]);;\
    push (@{$_warntypesraw},[("call","tos_hailing_frequencies_open.mp3","sleep 4;;","60")]);;\
\
    for (my $i=0;; $i < @{$_warntypesraw};; $i++) {\
        push (@{$_warntypes},$_warntypesraw[$i][0]);;\
        $_warntype{$_warntypesraw[$i][0]}{jingle}   = $_warntypesraw[$i][1];;\
        $_warntype{$_warntypesraw[$i][0]}{pause}    = $_warntypesraw[$i][2];;\
        $_warntype{$_warntypesraw[$i][0]}{loudness} = $_warntypesraw[$i][3];;\
    }\
\
    $_debugmode = AttrVal("$SELF","debugmode","off") eq "on";;\
    fhem("deletereading $SELF (DEBUG.*|error.*)");;\
\
    sub speakcmd {\
        my ($myaudience,$mywarntype,$mymessagefulltext) = @_;;\
        my $returncmd = "";;\
        $returncmd .= "set ".$_devices{$myaudience}{device}." ".$_devices{$myaudience}{speakcmd}." ";;\
        $returncmd .= ($_devices{$myaudience}{addloud} eq "1" ? $_warntype{$mywarntype}{loudness} : "")." $mymessagefulltext;;";;\
        set_Reading("DEBUG.speakcmd",$returncmd) if ($_debugmode);;\
        return $returncmd;; \
    }\
    sub jinglecmd {\
        my ($myaudience,$mywarntype) = @_;;\
        my $returncmd = "";;\
        if ($_devices{$myaudience}{canjingle} eq "1") {\
            $returncmd .= "set ".$_devices{$myaudience}{device}." notify ".$_warntype{$mywarntype}{loudness};;\
            $returncmd .= " http://sonostts.fritz.box:5601/cache/".$_warntype{$mywarntype}{jingle}.";;";;\
        }\
        set_Reading("DEBUG.jinglecmd",$returncmd) if ($_debugmode);;\
        return $returncmd;;\
    }\
} \
\
incomingmessage {\
    my $messageraw = [$SELF:message];;\
    my ($transportmethod, $audience, $warntype, @messagetext) = split(/ /, $messageraw);; \
    my $messagefulltext = join(" ", @messagetext);;\
    my $cmd             = "";;\
\
    if ($_debugmode) {\
        set_Reading("DEBUG.transportmethod",  $transportmethod    ,1);;\
        set_Reading("DEBUG.audience",         $audience           ,1);;\
        set_Reading("DEBUG.warntype",         $warntype           ,1);;\
        set_Reading("DEBUG.message.content",  $messagefulltext    ,1);;\
        set_Reading("DEBUG.message.raw",      $messagefulltext    ,1);;\
    }\
\
    if (not grep {$_ eq $audience} (@{$_targets},"alle")) {\
        set_Reading("error", "invalid audience $audience Allowed: ".join(" ", (@{$_targets},"alle")));;\
        return;;\
    }\
    if (not grep {$_ eq $transportmethod} ("telegram","audio")) {\
        set_Reading("error", "invalid transportmethod $transportmethod");;\
        return;;\
    }\
    if (not grep {$_ eq $warntype} @{$_warntypes}) {\
        set_Reading("error", "invalid warntype $warntype Allowed: ".join(" ", @{$_warntypes}));;\
        return;;\
    }\
\
    if ($transportmethod eq "telegram" && $audience eq "Heiko") {\
        $cmd .= "set HLTelegramBot message $messagefulltext;;";; \
    } elsif ($warntype eq "sleep" && $transportmethod eq "audio" && $audience ne "alle") {\
        ## Beim "Gute Nacht" erst der Text dann der Schnarch-Jingle\
        $cmd .= speakcmd($audience,$warntype,$messagefulltext);; \
        $cmd .= $_warntype{$warntype}{pause};;\
        $cmd .= jinglecmd($audience,$warntype);;\
    } elsif ($warntype ne "sleep" && $transportmethod eq "audio" && $audience ne "alle") {\
        ## Sonst umgekehrt, erst Jingle, dann Text\
        $cmd .= jinglecmd($audience,$warntype);;\
        $cmd .= $_warntype{$warntype}{pause};;\
        $cmd .= speakcmd($audience,$warntype,$messagefulltext);; \
    } elsif ($warntype ne "sleep" && $transportmethod eq "audio" && $audience eq "alle") {\
        for (my $i=0;; $i < @{$_devicesraw};; $i++) {\
            $cmd .= jinglecmd($_devicesraw[$i][0],$warntype);;\
        }\
        $cmd .= $_warntype{$warntype}{pause};;\
        for (my $i=0;; $i < @{$_devicesraw};; $i++) {\
            $cmd .= speakcmd($_devicesraw[$i][0],$warntype,$messagefulltext);; \
        }\
    };;\
    \
    fhem($cmd) if ($cmd ne "");;\
    set_Reading("DEBUG.finalcommand", $cmd, 1) if ($_debugmode);;\
}\

attr messaging userattr debugmode:on,off
attr messaging DbLogExclude .*
attr messaging debugmode on
attr messaging readingList message
attr messaging room Labor
attr messaging setList message:textField\


hydrotec

@Otto

Danke noch einmal für deine Unterstützung.
@svrooij/sonos-tts-polly ist schon etwas gewöhnungsbedürftig, vor allem die Dokumentation dazu.
Es ist ja definitiv nur eine Erweiterung zu node-sonos-ts, vermutlich.
Wie das alles zusammenhängt habe ich noch nicht rausgefunden.
Ehrlich gesagt, ist auch nicht so schlimm.
Mir geht es ähnlich wie Sebastian, ist nicht unbedingt "Prio rot".  ;)

Doch mal eine andere Frage, ohne dazu irgendetwas gelesen zu haben.
FHEM hat doch ein eigenes Text2Speech Modul,
könnte man das nicht auch für Sonos verwenden?

Gruß, Karsten

Otto123

Hallo Karsten,

so ist es und so ist die default Einrichtung. Steht auch so im Wiki https://wiki.fhem.de/wiki/Sonos2mqtt

Zu sonos-tts-polly: Es ist alles eine Erweiterung der Erweiterung :) letztlich ist es ein Zoo aus nodejs Modulen.
Man kann npm sicher sagen: Installiere nicht in default sondern in diesen Pfad, hab ich aber irgendwie nicht verstanden wie.
Man kann auch sicher dieses /usr/bin/sonos-tts-polly Script starten - ich habe aber auch nicht verstanden wie :)
Letztlich hat das Ding ein paar Parameter beim Aufruf - find ich nicht so kompliziert. Die nodejs Dokumentation sind zum großen Teil automatisch generiert, besser als nix aber eben auch nur so gut wie sich es der Programmierer ausgedacht hat. Und der weiß ja wie sein Programm funktioniert ;)

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

hydrotec

Zitat von: Otto123
so ist es und so ist die default Einrichtung. Steht auch so im Wiki https://wiki.fhem.de/wiki/Sonos2mqtt

Hast du das heute Nacht noch schnell eingefügt?  ;)
Ne, hab ich, vor lauter lass mich auch mit, komplett überlesen.  :-[
Dankeschön für den Hinweis, werde es die Tage so versuchen.

Angenehmen Tag noch.  8)
Gruß, Karsten

LordVoodoo

Hallo zusammen,

mal ungeachtet von meinen TIDAL-Problemen, habe ich einen anderen Ansatz gewählt für die Senderauswahl.
Ich lasse mir die Favoriten als einzelne FHEM-Objekte erstellen und habe einen Befehl "play_on" hinterlegt, um so den jeweiligen Favoriten auf einem bestimmten Gerät zu starten.

Im Moment sieht das wie folgt aus:

Notify zur Anlage der Favoriten:
define Rule_Sonos_Favoriten_anlegen notify .*:Favorites:.* {
my $regex = "/(?:\"Title.:\"(.*?)\",\"UpnpClass\":\"(.*?)\",.+?\"TrackUri\":\"(.*?)\")+/mg";
my $fav_json;

my $play_on = "-";

my @speakers =devspec2array("a:model=sonos2mqtt_speaker");

foreach my $speaker (@speakers)
{
  if ($defs{$speaker})
  {
    $play_on = $play_on eq "-" ? "play_on:".$speaker : $play_on.",".$speaker;
  }
}

my $decoded = $EVENT =~ s/^Favorites: //r;
$decoded = decode_json($decoded);
my $counter = 0;

fhem("delete TYPE=DUMMY:Filter=a:genericDeviceType=Sonos_Favorit");

foreach my $fav (@{$decoded->{'Result'}})
{
  fhem("define Sonos_Favorit_$counter DUMMY");
  fhem("attr Sonos_Favorit_$counter genericDeviceType Sonos_Favorit");
  fhem("setreading Sonos_Favorit_$counter title ".$fav->{"Title"});

  fhem("attr Sonos_Favorit_$counter alias Sonos - ".$fav->{"Title"});
  fhem("setreading Sonos_Favorit_$counter url ".$fav->{"TrackUri"});
  fhem("setreading Sonos_Favorit_$counter class ".$fav->{"UpnpClass"});

  $counter++;
  }
fhem("attr a:genericDeviceType=Sonos_Favorit setList $play_on");
}


Notify zum Starten des Abspielen
define Rule_Favorit_Sonos_starten notify Sonos_Favorit.*:play_on\s.* {

fhem("setreading $SELF debugging $EVTPART1");
my $url = ReadingsVal($NAME, "url", "-");

if ($defs{$EVTPART1} and $url ne "-")
{
   fhem("set $EVTPART1 playUri $url");
}
}


Man könnte dieses Szenario jetzt noch erweitern um folgenden Vorgang:
Wenn ein Gerät bereits einen Stream abspielt und ein weiteres Gerät wird mit dem gleichen Favoriten "beauftragt", dann wird das zweite Gerät in eine Gruppe mit dem ersten aufgenommen.