Sonos2mqtt - vielleicht hat jemand Lust mitzumachen

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

Vorheriges Thema - Nächstes Thema

TomLee

#435
Habs geschafft aus dem Json
{"Result":[{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s296020q.png","Title":"011.FM-NonStop60s","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/26","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s296020?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F475_288x162_2020-01-22-10-30-00-920.png_180.jpg","Title":"1A Deutsche Hits","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/41","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_475?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F1944_288x162_2019-02-12-13-40-09-357.png_640.jpg","Title":"COSMO Chillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/30","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_1944?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s20295/images/logoq.png","Title":"DASDING 92.5 (Euro-Hits)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/34","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s76488?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s84548/images/logoq.jpg","Title":"die neue welle 101.8 (Rock)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/39","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s84548?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s65628q.png","Title":"FM نجوم 100.6 (Arabisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/29","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s65628?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"Title":"Hitradio Ö3 99.9 (Österreichisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/37","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s8007?sid=254&flags=8224&sn=0","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},{"Title":"Hörbücher","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/32","ParentId":"FV:2","TrackUri":"x-rincon-playlist:RINCON_000E58F7F67C01400#S://192.168.188.26/OwnMusic/Hörbücher","ProtocolInfo":"x-rincon-playlist:*:*:*"},{"Title":"Ordner","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/31","ParentId":"FV:2"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s97066q.png","Title":"PsyRadioChillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/15","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s97066?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"Title":"Tony Rebel","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/28","ParentId":"FV:2","TrackUri":"undefined"}],"NumberReturned":11,"TotalMatches":11,"UpdateID":1}


welcher von einem sonos/RINCON_000E58F7F67C01400/control {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Reply"}} zurückkommt, die Favoritennamen und dazugehörigen TrackUris in einer sortierten Liste jeweils in eigene Readings zu schreiben.

Sortiert heißt beide Listen sind gleich sortiert, am Beispiel unten steht im Reply_Favorites Reading 1A Deutsche Hits an Position 3 der Liste, die zugehörige TrackUri steht dann auch an dritter Position von Reply_TrackUris.

Zum einfachen nachvollziehen empfiehlt sich erstmal in dem push {push (@a, "$value")}} $key mit reinzunehmen, zu schauen was passiert und dann das my @s = sort @a; rauszunehmen um zu sehen was es bedeutet eine unsortierte Liste zu haben.

defmod SonosControl MQTT2_DEVICE
attr SonosControl IODev m2s
attr SonosControl getList Favorites:noArg Reply_Favorites sonos/RINCON_000E58F7F67C01400/control {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Reply"}}\

attr SonosControl readingList sonos/RINCON_([0-9A-Z]+)/Reply:.* { json2nameValue($EVENT,'',$JSONMAP,'TrackUri')}\
sonos/RINCON_([0-9A-Z]+)/Reply:.* { json2nameValue($EVENT,'',$JSONMAP,'Title')}\
sonos/RINCON_([0-9A-Z]+)/Reply:.* {my $werte = json2nameValue($EVENT);;my @a =0;; while ( my ($key, $value) = each (%$werte)) {if ($key =~ m,Result_._Title,g){push (@a, "$value")}};;my @s = sort @a;; my $g =join (',',@s);;{"Reply_Favorites"=>$g}}\
sonos/RINCON_([0-9A-Z]+)/Reply:.* {my $werte = json2nameValue($EVENT);;my @a =0;; while ( my ($key, $value) = each (%$werte)) {if ($key =~ m,Result_._TrackUri,g){push (@a, "$value")}};;my @s = sort @a;;;; my $g =join (',',@s);;{"Reply_TrackUris"=>$g}}
attr SonosControl room MQTT2_DEVICE
attr SonosControl setList playUri:textField {fhem("set $NAME setAVTUri $EVTPART1;; sleep 1;; set $NAME play")}\
setAVTUri:textField sonos/RINCON_000E58F7F67C01400/control { "command": "setavtransporturi",  "input": "$EVTPART1"}\
play:noArg sonos/RINCON_000E58F7F67C01400/control { "command": "play" }\
StartRadio:select,{ "1,2,3";;}

setstate SonosControl play
setstate SonosControl 2020-08-01 21:11:55 Reply_Favorites 0,011.FM-NonStop60s,1A Deutsche Hits,COSMO Chillout,DASDING 92.5 (Euro-Hits),FM نجوم 100.6 (Arabisch),Hitradio Ö3 99.9 (Österreichisch),Hörbücher,Ordner,die neue welle 101.8 (Rock)
setstate SonosControl 2020-08-01 21:11:55 Reply_TrackUris 0,x-rincon-playlist:RINCON_000E58F7F67C01400#S://192.168.188.26/OwnMusic/Hörbücher,x-sonosapi-stream:rpde_svc_1944?sid=232&flags=32&sn=4,x-sonosapi-stream:rpde_svc_475?sid=232&flags=32&sn=4,x-sonosapi-stream:s296020?sid=254&flags=8224&sn=0,x-sonosapi-stream:s65628?sid=254&flags=8224&sn=0,x-sonosapi-stream:s76488?sid=254&flags=8224&sn=0,x-sonosapi-stream:s8007?sid=254&flags=8224&sn=0,x-sonosapi-stream:s84548?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_10_Title PsyRadioChillout
setstate SonosControl 2020-08-01 21:11:56 Result_10_TrackUri x-sonosapi-stream:s97066?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_11_Title Tony Rebel
setstate SonosControl 2020-08-01 21:11:56 Result_11_TrackUri undefined
setstate SonosControl 2020-08-01 21:11:55 Result_1_Title 011.FM-NonStop60s
setstate SonosControl 2020-08-01 21:11:56 Result_1_TrackUri x-sonosapi-stream:s296020?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_2_Title 1A Deutsche Hits
setstate SonosControl 2020-08-01 21:11:56 Result_2_TrackUri x-sonosapi-stream:rpde_svc_475?sid=232&flags=32&sn=4
setstate SonosControl 2020-08-01 21:11:55 Result_3_Title COSMO Chillout
setstate SonosControl 2020-08-01 21:11:56 Result_3_TrackUri x-sonosapi-stream:rpde_svc_1944?sid=232&flags=32&sn=4
setstate SonosControl 2020-08-01 21:11:55 Result_4_Title DASDING 92.5 (Euro-Hits)
setstate SonosControl 2020-08-01 21:11:56 Result_4_TrackUri x-sonosapi-stream:s76488?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_5_Title die neue welle 101.8 (Rock)
setstate SonosControl 2020-08-01 21:11:56 Result_5_TrackUri x-sonosapi-stream:s84548?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_6_Title FM نجوم 100.6 (Arabisch)
setstate SonosControl 2020-08-01 21:11:56 Result_6_TrackUri x-sonosapi-stream:s65628?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_7_Title Hitradio Ö3 99.9 (Österreichisch)
setstate SonosControl 2020-08-01 21:11:56 Result_7_TrackUri x-sonosapi-stream:s8007?sid=254&flags=8224&sn=0
setstate SonosControl 2020-08-01 21:11:55 Result_8_Title Hörbücher
setstate SonosControl 2020-08-01 21:11:56 Result_8_TrackUri x-rincon-playlist:RINCON_000E58F7F67C01400#S://192.168.188.26/OwnMusic/Hörbücher
setstate SonosControl 2020-08-01 21:11:55 Result_9_Title Ordner



attr SonosControl readingList sonos/RINCON_([0-9A-Z]+)/Reply:.* { json2nameValue($EVENT,'',$JSONMAP,'TrackUri')}\
sonos/RINCON_([0-9A-Z]+)/Reply:.* { json2nameValue($EVENT,'',$JSONMAP,'Title')}\


Ist nur zum Test was die neue option Filter daraus macht.

Mein Gedanke ist jetzt einen setter  (entsprechend dem setter playUri) zu erstellen bspw. StartFavorit der mit Hilfe des select widget alle Favoritennamen zur Verfügung stellt, die in Reply_Favorites stehen.
Mit Auswahl eines Favoritennamen soll geprüft an welcher Position der Favorit in der Liste von Reply_Favorites steht und der setter mit der zugehörigen Position aus Reply_TrackUris ausgeführt werden.

Meine erste bescheidene Frage zum ersten Schritt dahin, wie bekomme ich im ersten Schritt die Liste aus ReadingsVal($NAME,"Reply_Favorites","unknown") select angehangen, bekomm es nicht hin ?

Sowas oder auch exotischere Varianten klappen bisher nicht:

StartRadio:select,{ ReadingsVal($NAME,"Reply_Favorites","unknown") }
StartRadio:{my $rf = ReadingsVal("SonosControl","Reply_Favorites","unknown");"select,".$rf." bla"}
StartRadio:{"select,".$rf." bla";my $rf = ReadingsVal("SonosControl","Reply_Favorites","unknown");}
StartRadio:select,{ "1,2,3";}


edit:
Auch nicht mit setList komplett in Perl:
{my $rf = ReadingsVal("SonosControl","Reply_Favorites","unknown");;"StartRadio:select,".$rf." bla";;}

Einen Schritt weiter, es kann ja nicht klappen mit Leereichen in den Favoriten.

Aber auch zum Test mit
setstate SonosControl 2020-08-02 14:11:58 test 1,2,3
klappts nicht
{my $rf = ReadingsVal("SonosControl","test","unknown");"StartRadio:select,".$rf." bla";}
StartRadio:select,{my $rf = ReadingsVal("SonosControl","test","unknown");$rf." bla";}


Lösung hier gefunden.
So klappts schonmal aus der Befehlszeile (dachte wenn man ein Attribute setzt gibts ein rotes ?, ist hier nicht so)

{my $rf = ReadingsVal("SonosControl","test","unknown");;fhem('attr SonosControl setList StartRadio:select,'.$rf." bla");;}

So ersetzt man erstmal einmal die setList aus der Befehlszeile, es braucht noch eine Lösung das die Zeile StartRadio in setList nicht übernommen wird/zuvor gelöscht wird wenn zuvor vorhanden (doch alles mit rotem ?):

{my $rf = ReadingsVal("SonosControl","Reply_Favorites","unknown");;$rf =~ s/ /./g;;my $sl= AttrVal("SonosControl","setList","");; $sl =~ s/;/;;/g;;fhem('attr SonosControl setList StartRadio:select,'.$rf.' bla'."\n".$sl)}

Otto123

#436
Moin,

Deine letzte Frage habe ich schon mal gelöst. Meine Variante zur Erweiterung der setList war ja so
{my @list = devspec2array('MQTT2_RINCON_.*');;\
foreach (@list) {\
   my $setList=AttrVal($_,'setList','');;\
   my @arr=split("\n",$setList);;\
   if ($setList!~m/speak:textField/) {\
     push @arr , q(  speak:textField { my $tts="SonosTTS";;my $payload = $EVENT;;$payload =~ s/$EVTPART0 $EVTPART1 //g;; fhem("setreading $tts Player $NAME;;setreading $tts volume $EVTPART1;;set $tts tts $payload");;"{}"});;\
   }\
   $setList=join "\n",@arr;;\
   $setList=~s/;;/;;;;/g;;\
   fhem("attr $_ setList $setList")\
}}


Die Abfrage if ($setList!~m/StartRadio:select/) {} verhindert die Ergänzung wenn der entsprechende Setter schon da ist.

Aber was ich noch nicht ganz verstehe, damit wird je die Auswahl statisch beim Eintrag in den Setter geholt? Ok ist sicher erträglich :)

Aber muss man eigentlich dort eine Auswahlliste haben? Geht nicht ein Textfeld mit Suchbegriff?

So in der Art, mein Ansatz aus #419 aufgreifend:
playFav:textField {use JSON;my $uri='';my @ea=split(' ', $EVENT);shift @ea;my $search = join ' ',@ea;my $jlist = ReadingsVal('SonosControl','Replykomplett','');my $decoded = decode_json($jlist);my @arr=@{$decoded->{'Result'}};foreach (@arr) {if ($_->{'Title'} =~ /$search/i){$uri = $_->{'TrackUri'} }};fhem("set $NAME playUri $uri") if ($uri ne '')}
Ist nur mal ein Arbeitsversuch - ich weiß da ist jetzt noch ein fester Name drin.
Vielleicht bekomme ich den Code noch schöner ;)

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

PatrickR

Zitat von: Otto123 am 01 August 2020, 14:58:44
ja ich habe so etwas ähnliches. Ich habe aber bisher den Eindruck, es hat nicht nur was mit dem Player zu tun der kommt und geht sondern es tritt bei oder in Kombination mit Gruppenänderung über sonos2mqtt  auf?
Ich benutze eigentlich nur sehr sehr selten Gruppen. Allerdintgs kann ich natürlich nicht ausschließen, dass AirSonos, das ich ebenfalls benutze, irgendwie dazwischenpfuscht. Das ist aber alles zugegebenermaßen Kaffeesatzleserei.

Zitat von: Otto123 am 01 August 2020, 14:58:44
Nur Player aus und zwei Stunden wieder an funktioniert.
Edit: Nein funktioniert aktuell nicht - gerade probiert player war aus, angemacht in sonos2mqtt wird die topologie nicht aktualisiert :(
Ich dachte das hat schon funktioniert  ???
Nach meiner Stichprobe mit n=1 hat es nicht funktioniert. Müsste das mal etwas strukturierter testen.

Zitat von: Otto123 am 01 August 2020, 14:58:44
Ein pm2 restart sonos2mqtt behebt das Problem in jedem Fall.
Jo bei mir ebenfalls. Auch wenn ich einen Docker-Container benutze. Dann sehe ich wenigstens den ganzen Node-Overhead nicht ;)

Wäre natürlich toll, wenn man die Fehlersituation detektieren könnte. Hatte auch schon überlegt, ob ich das Event, das den Connect ausschaltet in FHEM abfange und dann den Container neu starte. Das wäre natürlich die Holzhammermethode. Der Autor scheint momentan an einer Möglichkeit zu arbeiten, über einen mqtt-Befehl die subscriptions zu aktualisieren:
https://github.com/svrooij/sonos2mqtt/issues/112#issuecomment-664548518

Patrick
lepresenced - Tracking von Bluetooth-LE-Tags (Gigaset G-Tag) mittels PRESENCE

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning." - Rich Cook

TomLee

ZitatDie Abfrage if ($setList!~m/StartRadio:select/) {} verhindert die Ergänzung wenn der entsprechende Setter schon da ist.

Hab ich mich ungenau ausgedrückt, die Zeile sollte ersetzt werden, es könnten ja neue Favoriten dazugekommen sein.


Zitat
Aber was ich noch nicht ganz verstehe, damit wird je die Auswahl statisch beim Eintrag in den Setter geholt? Ok ist sicher erträglich

Mein Ansatz wäre bei einem get Favorites die setList aktualisieren

attr SonosControl getList Favorites:noArg Reply_Favorites sonos/RINCON_000E58F7F67C01400/control {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Reply"}}



ZitatAber muss man eigentlich dort eine Auswahlliste haben? Geht nicht ein Textfeld mit Suchbegriff?

Hab ich noch nicht ganz verstanden, ist das nicht vergleichbar mit stochern im Dunkeln ?



playFav:textField {use JSON;my $uri='';my @ea=split(' ', $EVENT);shift @ea;my $search = join ' ',@ea;my $jlist = ReadingsVal('SonosControl','Replykomplett','');my $decoded = decode_json($jlist);my @arr=@{$decoded->{'Result'}};foreach (@arr) {if ($_->{'Title'} =~ /$search/i){$uri = $_->{'TrackUri'} }};fhem("set $NAME playUri $uri") if ($uri ne '')}


Das schon cool, mir gefällt die Verwendung von use JSON aber nicht, das muss auch anders gehen.




Was ich gerne wissen würde (das nicht jeder sein eigenes Süppchen kocht) und jeder mit den gleichen Daten arbeitet, ob das setzen der zwei Readings Reply_Favorites und Reply_TrackUris eine gute Idee war und so im Template eingebaut wird oder nicht ?
So müsste man nicht immer den JSON in Replykomplett auseinandernehmen um damit zu arbeiten oder ist es das Ziel nur mit dem Reading auszukommen ?
Find das eigentlich, gut zumindest das Reading Reply_Favorites.

Otto123

Zitat von: TomLee am 04 August 2020, 12:23:46
Hab ich noch nicht ganz verstanden, ist das nicht vergleichbar mit stochern im Dunkeln ?
Naja die List sehe ich ja in der App. Ich habe sie ja auch dort erstellt. Kann ich da anschauen und auswählen...
Was ich in FHEM will und brauche ist: Starte einen (bestimmten) Radiosender oder Musik.
In dem normalen Sonos Modul war es für mich immer Krampf herauszufinden wie die Sender jetzt geschrieben werden (müssen) damit sie FHEM akzeptiert. Mit meiner Methode gebe ich irgendwie eine Teil Begriff des Favoriten an der passt  8)

Die Favoriten aktualisieren geht einfach und alles steht in nur einem Reading.

JSON wird doch bei MQTT sowieso verwendet, warum soll man das nicht nehmen?

Ich finde die Favoriten Liste an jedem Player zu haben unlogisch, einmal an der Bridge reicht doch? Mein zusätzliches Gerät war nur zum Test, ich finde jetzt die Liste gehört in die Bridge und damit geht es.
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

Zitat von: TomLee am 04 August 2020, 12:23:46
Hab ich mich ungenau ausgedrückt, die Zeile sollte ersetzt werden, es könnten ja neue Favoriten dazugekommen sein.
Ich habe da noch was gefunden:
{my @arr =(1,2,3,4,5);;my $search=2;;
my @orr = grep {$_ ne $search} @arr;;
return join ",",@orr}


Also alte Zeile löschen dann neue Zeile rein :)
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

87insane

Sagt mal... Ich lese hier die ganze Zeit voller Staunen mit...
Ihr lest die Fav aus. Könnt ihr das nicht auch mit den Gruppen machen? Das wäre auch schön. Das wollte ich ja eigentlich machen aber ich würde das nicht auf dem Level hin bekommen, wie ihr beide hier!

TomLee

ZitatIch finde die Favoriten Liste an jedem Player zu haben unlogisch, einmal an der Bridge reicht doch? Mein zusätzliches Gerät war nur zum Test, ich finde jetzt die Liste gehört in die Bridge und damit geht es.

Mein zusätzliches Gerät auch  ;)

Zitat
Ich habe da noch was gefunden:
Das mit dem ersetzen schau ich mir später an.


Mit dem ReadingList-Eintrag unten wird nach Auswahl eines Favoritennamen im setter der jeweilige Favorit abgespielt, alles aus dem JSON im Reading Reply_Favorites in der Bridge steht.
Die Favoritennamen können ja auch Leerzeichen enthalten, dann klappt das mit dem select-Widget nicht, daher hab ich die erstmal mit Punkten ersetzt.
Oben war noch ein Denkfehler beim sortieren, das klappt jetzt.

Der Code ist nicht optimal, einiges verbesserungswürdig (unter anderem auch),ist mir klar aber funzt und ich spiel noch weiter.


playFav:select,0,011.FM-NonStop60s,1A.Deutsche.Hits,COSMO.Chillout,DASDING.92.5.(Euro-Hits),FM.نجوم.100.6.(Arabisch),Hitradio.Ö3.99.9.(Österreichisch),Hörbücher,PsyRadioChillout,die.neue.welle.101.8.(Rock) {my $werte = json2nameValue(ReadingsVal("MQTT2_Sonos_Bridge","Reply_Favorites","unknown"));my @ar;while ( my ($key, $value) = each (%$werte)) {if ($key =~ m,Result_._Title,g){push (@ar, "$key $value")}};my @s = sort @ar;my $g =join (',',@s);$g =~ s/ /./g;$g =~ s/Result_._Title.//g;my $werte2 = json2nameValue(ReadingsVal("MQTT2_Sonos_Bridge","Reply_Favorites","unknown"));my @ar2;while ( my ($key2, $value2) = each (%$werte2)) {if ($key2 =~ m,Result_._TrackUri,g){push (@ar2,"$key2 $value2")}};my @s2 = sort @ar2;my $g2 =join (',',@s2);$g2 =~ s/Result_._TrackUri.//g;my @a = split(',',$g); my ($index) = grep { $a[$_] eq $EVTPART1 } (0 .. @a-1);;my $d = defined $index ? $index : -1;my @b = split(',',$g2);my $u = $b[$d];fhem("set $NAME setAVTUri $u; sleep 1; set $NAME play")}

TomLee

Zitat{
my $werte = json2nameValue(ReadingsVal("MQTT2_Sonos_Bridge","Reply_Favorites","unknown"));
my @ar;
while ( my ($key, $value) = each (%$werte)) {if ($key =~ m,Result_._Title,g){push (@ar, "$key $value")}};
my @s = sort @a;
my $g =join (',',@s);
$g =~ s/ /./g;$g =~ s/Result_._Title.//g;

my $werte2 = json2nameValue(ReadingsVal("MQTT2_Sonos_Bridge","Reply_Favorites","unknown"));
my @ar2;
while ( my ($key2, $value2) = each (%$werte2)) {if ($key2 =~ m,Result_._TrackUri,g){push (@ar2,"$key2 $value2")}};
my @s2 = sort @ar2;;
my $g2 =join (',',@s2);$g2 =~ s/Result_._TrackUri.//g;


my @a = split(',',$g); my ($index) = grep { $a[$_] eq $EVTPART1 } (0 .. @a-1);;
my $d = defined $index ? $index : -1;
my @b = split(',',$g2);
my $u = $b[$d];
fhem("set $NAME setAVTUri $u; sleep 1; set $NAME play")}

Was ich einfach nicht hinbekomme den roten Teil in einer Schleife abzuwickeln oder geht das nicht.
Hinter dem if ein weiteres (else)if {if ($key2 =~ m,Result_._TrackUri,g){push (@ar2,"$key2 $value2")}}, welches das zweite Array (@ar2) gleich mit füllt, dann wär das alles viel kürzer.

Otto123

#444
Das mit deinen Sortierschleifen versteh ich noch nicht. Vielleicht wenn ich es später nochmal lese :) - vielleicht siehst Du es ja noch zu kompliziert?
Warum Namen und Uri getrennt sortieren? Warum nicht nur die Namen sortieren? Damit findest Du doch die Uri im JSON Array?

Erstmal mein Beispiel für die Favoriten zum durchsuchen.
Sämtlicher Code ist für die Raw Def, einfach reinwerfen und excute. ;)
Drei Schritte:

Edit Code korrigiert!

Modifikation der Bridge (ja man kann es auch mit einer Zeile per Hand machen :) ich wollte das universelle "Script" zeigen)
{my @devlist = devspec2array('model=sonos2mqtt_bridge');;\
my $attr = 'readingList';;\
my $search = 'sonos/RINCON_([0-9A-Z]+)/Favorites';;\
my $item = q(  sonos/RINCON_([0-9A-Z]+)/Favorites:.* Favorites);;\
foreach (@devlist) {\
   my @arr = grep {$_ !~ $search} split("\n",AttrVal($_,$attr,''));;\
   push @arr,$item;;\
   my $val = join "\n",@arr;;\
   $val =~ s/;;/;;;;/g;;\
   fhem("attr $_ $attr $val")}\
return "$attr in ".scalar(@devlist)." Definitionen ergänzt"\
}

Den Befehl bei allen Playern nachrüsten
{my @devlist = devspec2array('MQTT2_RINCON_.*');;\
my $attr = 'setList';;\
my $search = 'playFav:textField';;\
my $item = q(  playFav:textField {use JSON;;my $uri='';;my @ea=split(' ', $EVENT);;shift @ea;;my $search = join ' ',@ea;;my $jlist = ReadingsVal((devspec2array('model=sonos2mqtt_bridge'))[0],'Favorites','');;my $decoded = decode_json($jlist);;my @arr=@{$decoded->{'Result'}};;foreach (@arr) {if ($_->{'Title'} =~ /$search/i){$uri = $_->{'TrackUri'} }};;fhem("set $NAME playUri $uri") if ($uri ne '')});;\
foreach (@devlist) {\
   my @arr = grep {$_ !~ $search} split("\n",AttrVal($_,$attr,''));;\
   push @arr,$item;;\
   my $val = join "\n",@arr;;\
   $val =~ s/;;/;;;;/g;;\
   fhem("attr $_ $attr $val")}\
return "$attr in ".scalar(@devlist)." Definitionen ergänzt"\
}

Dann die Favoriten lesen:
set alias=<ein player der Wahl> x_raw_payload {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Favorites"}}

Und dann mit set <player> playFav suchstring den Favoriten starten.

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

TomLee

Zitat{"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Favorites"}}

Weshalb nimmst auf einmal Favorites statt wie zuvor Reply ?
Bei beiden kommt der gleiche JSON.

Hast das mal mit dem getter ausprobiert, bei mir ist das jetzt schon Standard.

defmod MQTT2_Sonos_Bridge MQTT2_DEVICE mqttjs_448faffc
attr MQTT2_Sonos_Bridge IODev m2s
attr MQTT2_Sonos_Bridge bridgeRegexp sonos/(RINCON_[A-Z0-9]+)[:/].* "$1"
attr MQTT2_Sonos_Bridge getList AllFavorites:noArg Reply_All sonos/RINCON_000E58F7F67C01400/control {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Reply"}}\
Favorite:noArg Favorites sonos/RINCON_000E58F7F67C01400/control {"command": "adv-command","input": {"cmd": "GetFavorites","reply": "Favorites"}}
attr MQTT2_Sonos_Bridge icon mqtt_bridge_2
attr MQTT2_Sonos_Bridge model sonos2mqtt_bridge
attr MQTT2_Sonos_Bridge readingList sonos/connected:.* connected\
  homeassistant/music_player/RINCON_([0-9A-Z]+)/sonos/config:.* { $TOPIC =~ m,(RINCON_[0-9A-Z]+),;; { "config_$1"=>$EVENT }}\
  sonos/status/[^/]+/avtransport:.* {}\
  sonos/status/[^/]+/renderingcontrol:.* {}\
sonos/RINCON_([0-9A-Z]+)/Reply:.* Reply_All\
  sonos/RINCON_([0-9A-Z]+)/Favorites:.* Favorites
attr MQTT2_Sonos_Bridge room MQTT2_DEVICE

setstate MQTT2_Sonos_Bridge 2020-08-04 17:25:06 Favorites {"Result":[{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s296020q.png","Title":"011.FM-NonStop60s","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/26","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s296020?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F475_288x162_2020-01-22-10-30-00-920.png_180.jpg","Title":"1A Deutsche Hits","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/41","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_475?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F1944_288x162_2019-02-12-13-40-09-357.png_640.jpg","Title":"COSMO Chillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/30","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_1944?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s20295/images/logoq.png","Title":"DASDING 92.5 (Euro-Hits)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/34","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s76488?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s84548/images/logoq.jpg","Title":"die neue welle 101.8 (Rock)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/39","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s84548?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s65628q.png","Title":"FM نجوم 100.6 (Arabisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/29","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s65628?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"Title":"Hitradio Ö3 99.9 (Österreichisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/37","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s8007?sid=254&flags=8224&sn=0","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},{"Title":"Hörbücher","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/32","ParentId":"FV:2","TrackUri":"x-rincon-playlist:RINCON_000E58F7F67C01400#S://192.168.188.26/OwnMusic/Hörbücher","ProtocolInfo":"x-rincon-playlist:*:*:*"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s97066q.png","Title":"PsyRadioChillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/15","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s97066?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"}],"NumberReturned":9,"TotalMatches":9,"UpdateID":3}
setstate MQTT2_Sonos_Bridge 2020-08-04 17:18:50 Reply_Favorites {"Result":[{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s296020q.png","Title":"011.FM-NonStop60s","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/26","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s296020?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F475_288x162_2020-01-22-10-30-00-920.png_180.jpg","Title":"1A Deutsche Hits","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/41","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_475?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://dtu8ldmaopof3.cloudfront.net/i/https:%2F%2Fderpimagecache.s3.amazonaws.com%2Fimage%2F1944_288x162_2019-02-12-13-40-09-357.png_640.jpg","Title":"COSMO Chillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/30","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:rpde_svc_1944?sid=232&flags=32&sn=4","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s20295/images/logoq.png","Title":"DASDING 92.5 (Euro-Hits)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/34","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s76488?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-profiles.tunein.com/s84548/images/logoq.jpg","Title":"die neue welle 101.8 (Rock)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/39","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s84548?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s65628q.png","Title":"FM نجوم 100.6 (Arabisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/29","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s65628?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"},{"Title":"Hitradio Ö3 99.9 (Österreichisch)","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/37","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s8007?sid=254&flags=8224&sn=0","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},{"Title":"Hörbücher","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/32","ParentId":"FV:2","TrackUri":"x-rincon-playlist:RINCON_000E58F7F67C01400#S://192.168.188.26/OwnMusic/Hörbücher","ProtocolInfo":"x-rincon-playlist:*:*:*"},{"AlbumArtUri":"http://cdn-radiotime-logos.tunein.com/s97066q.png","Title":"PsyRadioChillout","UpnpClass":"object.itemobject.item.sonos-favorite","ItemId":"FV:2/15","ParentId":"FV:2","TrackUri":"x-sonosapi-stream:s97066?sid=254&flags=8224&sn=0","ProtocolInfo":"x-sonosapi-stream:*:*:*"}],"NumberReturned":9,"TotalMatches":9,"UpdateID":3}





ZitatErstmal mein Beispiel für die Favoriten zum durchsuchen.

Ich komm da nicht mit was das mit Suche zu tun hat, hatte das zuvor schon ausprobiert, ist aber auch cool.
Man muss doch exakt den Favoritennamen eingeben.
Aber wozu nochmal eingeben ? wenn er direkt schon im setter stehen kann, darauf war ich bisher irgendwie fixiert.
Und wie gesagt den setList Eintrag würde ich aktualisieren wenn man ein get Favorite an der Bridge ausführt.

Otto123

Zitat von: TomLee am 04 August 2020, 17:45:35
Weshalb nimmst auf einmal Favorites statt wie zuvor Reply ?


Ich komm da nicht mit was das mit Suche zu tun hat, hatte das zuvor schon ausprobiert, ist aber auch cool.
Man muss doch exakt den Favoritennamen eingeben.
Weil Du Reply_Favorites genommen hast :) ;D

Es ist doch "egal" was man hinschreibt man muss sich bloß mal auf eines einigen. Bei meinen Tests habe mal Reply und mal Replykomplett genommen. Da ich noch nicht wusste wie man das mal weiter verwendet. Jetzt ist mir klar: Ich frage die Favoriten ab und behalte die auch als JSON Array. Damit kann das Reading auch so heißen?


Du musst nicht exakt den Namen nehmen:($_->{'Title'} =~ /$search/i)
1. Ist Groß Klein egal.
2. muss es nur ein (signifikanter) Teil des vollen Favoriten Namen sein.

Wozu brauch ich die Klappliste wenn der Favorite doch eigentlich im Codetext steht? (Starte Radio früh wenn Licht im Bad angeht)

Das mit dem getter ist eine gute Idee, das muss ich noch verinnerlichen :)
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

Zitat von: 87insane am 04 August 2020, 16:40:31
Sagt mal... Ich lese hier die ganze Zeit voller Staunen mit...
Ihr lest die Fav aus. Könnt ihr das nicht auch mit den Gruppen machen? Das wäre auch schön. Das wollte ich ja eigentlich machen aber ich würde das nicht auf dem Level hin bekommen, wie ihr beide hier!
Ich finde keine weitere Möglichkeit in der Doku von Stephan die Gruppen auszulesen, außer wie wir das schon machen. Jeder Player weiß wozu er gehört, es gibt da keine zentralere Info - nach meinem Verständnis.
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

#448
Hallo Thomas,

Du brauchst doch keine einzelnen Readings mit Trackuris drin?
Du willst doch einfach eine sortierte Auswahlliste der Radios im Select Widget?

Die bekommst Du so direkt aus dem Reading (Raw Def):
{use JSON;;\
my $read = 'Favorites';;\
my $s = ReadingsVal((devspec2array('model=sonos2mqtt_bridge'))[0],$read,'');;\
my $decoded = decode_json($s);;\
my @arr  = @{$decoded->{'Result'}};;\
my @out;;\
foreach (@arr) {\
  my $temp=$_->{'Title'};;\
  $temp =~ s/ /./g;;\
  push @out,$temp}\
return join ',', sort @out}

Und dahinter nimmst Du dann meine Variante playFav um die trackuri direkt aus dem Reading zu holen/spielen?

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

TomLee

Du hast dir bisher noch nicht wirklich angeschaut was ich gemacht habe.

In #442 und #443 der Code ist nix anderes wie das was du jetzt zeigst mit decode_json.

extra für dich, für die Eingabe im "Editor"

{my $read = 'Favorites';;\
my $werte = json2nameValue(ReadingsVal((devspec2array('model=sonos2mqtt_bridge'))[0],$read,''));;\
my @ar;;\
while ( my ($key, $value) = each (%$werte)) {if ($key =~ m,Result_._Title,g){push (@ar, "$key $value")}};;\
my @s = sort @ar;;\
my $g =join (',',@s);;\
$g =~ s/ /./g;;\
$g =~ s/Result_._Title.//g;;\
$g;;}


Auch wenn ich mich sicher nicht ganz richtig Ausdrücke:

Du arbeitest bei decode_json, mein ich, mit einer Referenz auf ein Array.

Ich bekomme mit json2nameValue eine Referenz auf einen Hash zurück (brauch dazu nix mit Use einbinden) und arbeite dann damit.
Also nix anderes wie du, nur zwei verschiedene Wege. Und klar die Variante ohne zusätzliches Use ist mir lieber.

Verstanden hab ich schon etwas, aber begriffen ehrlich gesagt nur einen Bruchteil, sonst wär ich schon weiter.