Sonos2mqtt - vielleicht hat jemand Lust mitzumachen

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

Vorheriges Thema - Nächstes Thema

Beta-User

Nein, nicht bewußt. Bin davon ausgegangen, dass das klar wäre...

@Otto: Kannst du das bitte bei der nächsten Iteration auch  beachten?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Otto123

Zitat von: Beta-User am 18 Juli 2020, 14:42:22
Das mit line_in habe ich noch nicht verstanden. Bedeutet das, dass jeder Player seinen analogen Input an einen anderen Player weiterleiten kann?
Genauso ist es! Und witzigerweise geht das wohl mit dem digital Eingang nur über Gruppenbildung.

Das mit dem volumeUp/Down habe ich übersehen. Ich achte in Zukunft darauf.

Die Modellerkennung habe ich fast im Griff. Eine Codevariante ist fertig, aber die muss ich noch gesellschaftsfähig machen. ;)

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

87insane

Nur kurz da Handy:

@beta-user: liefere ich dir wie gewünscht. Hab aktuell nur keine Zeit am pc zu sitzen.

Habe das alles hier gerade auch nur überflogen aber wollte sagen das ich noch da bin und auch direkt, bei Zeit, weiter mache.

andre07

Da ich das hier mitlese wollte ich die Player mal neu anlegen um eventuelle Änderungen einzupflegen
nur leider sind jetzt alle Bedienfelder verschwunden also erst mal zurück auf alt

Alt:
define MQTT2_RINCON_5CAAFD243CDE01400 MQTT2_DEVICE RINCON_5CAAFD243CDE01400
attr MQTT2_RINCON_5CAAFD243CDE01400 DbLogExclude .*
attr MQTT2_RINCON_5CAAFD243CDE01400 IODev mqtt2server
attr MQTT2_RINCON_5CAAFD243CDE01400 alias Wohnzimmer
attr MQTT2_RINCON_5CAAFD243CDE01400 devStateIcon 0:10px-kreis-rot 1:10px-kreis-gelb 2:10px-kreis-gruen (0|1).(STOPPED|PAUSED_PLAYBACK):rc_BLANK 2.(STOPPED|PAUSED_PLAYBACK):rc_PLAY@green:play 2.(pause|stop):rc_STOP@red:play 2.PLAYING:rc_STOP@red:stop 2.(TRANSITIONING|play):rc_PLAY@yellow:stop 2.mute:audio_volume_mute@yellow:stop 2.volume:audio_volume_mid@yellow:stop 2.volumeDown:audio_volume_low@yellow:stop 2.volumeUp:audio_volume_high@yellow:stop 2.next:rc_NEXT@yellow:stop 2.previous:rc_PREVIOUS@yellow:stop (STOPPED|PAUSED_PLAYBACK).(false|previous|next|volumeDown|volumeUp|[0-9]+|CURRENT.*|NEXT.*|PAUSED_PLAYBACK):rc_BLANK \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.previous:rc_PREVIOUS:previous \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.next:rc_NEXT:next \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.volumeDown:rc_VOLDOWN:volumeDown \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.volumeUp:rc_VOLUP:volumeUp \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.false:rc_VOLUP:mute+true \b(?!(STOPPED|PAUSED_PLAYBACK)\b)\w+.true:rc_MUTE:mute+false
attr MQTT2_RINCON_5CAAFD243CDE01400 icon audio_volume_low
attr MQTT2_RINCON_5CAAFD243CDE01400 jsonMap volume_Master:volume mute_Master:mute transportState:state
attr MQTT2_RINCON_5CAAFD243CDE01400 model sonos2mqtt_speaker
attr MQTT2_RINCON_5CAAFD243CDE01400 readingList sonos/status/wohnzimmer/avtransport:.* { json2nameValue($EVENT,'AV_',$JSONMAP) }\
  sonos/status/wohnzimmer/renderingcontrol:.* { json2nameValue($EVENT,'REND_',$JSONMAP) }\
  sonos/RINCON_5CAAFD243CDE01400:.* { json2nameValue($EVENT,'',$JSONMAP) }\
  sonos/connected:.* bridgeConnected\
  sonos/RINCON_5CAAFD243CDE01400/error:.* { json2nameValue($EVENT) }
attr MQTT2_RINCON_5CAAFD243CDE01400 room MQTT2_DEVICE
attr MQTT2_RINCON_5CAAFD243CDE01400 setList stop:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "stop" }\
  play:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "play" }\
  pause:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "pause" }\
  toggle:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "toggle" }\
  volumeUp:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "volumeup" }\
  volumeDown:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "volumedown" }\
  volume:slider,0,1,100 sonos/RINCON_5CAAFD243CDE01400/control { "command": "volume", "input": $EVTPART1 }\
  mute:iconSwitch,false,rc_MUTE,true,rc_VOLUP { my $value = $EVTPART1 eq "true" ? "mute" : "unmute";;;; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "$value" } ) }\
  next:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "next" }\
  previous:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "previous" }\
  joinGroup:textField sonos/RINCON_5CAAFD243CDE01400/control { "command": "joingroup",  "input": "$EVTPART1"}\
  leaveGroup:noArg { my $value = ReadingsVal("RINCON_5CAAFD243CDE01400","groupName","all");; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "leavegroup",  "input": "$value" } ) }\
  setAVTUri:textField sonos/RINCON_5CAAFD243CDE01400/control { "command": "setavtransporturi",  "input": "$EVTPART1"}\
  notify:textField sonos/RINCON_5CAAFD243CDE01400/control { "command":"notify","input":{"trackUri":"$EVTPART2","onlyWhenPlaying":false,"timeout":10,"volume":$EVTPART1,"delayMs":700}}\
  x_raw_payload:textField { my $payload = $EVENT;;$payload =~ s/$EVTPART0 //g;; qq(sonos/RINCON_5CAAFD243CDE01400/control $payload)}\
  playUri:textField {fhem("sleep 1;; set $NAME play");; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "setavtransporturi",  "input": "$EVTPART1"})}\
  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");;"{}"}
attr MQTT2_RINCON_5CAAFD243CDE01400 stateFormat [$name:bridgeConnected]\
[$name:bridgeConnected].[$name:state]\
[$name:state].previous\
[$name:state].next\
[$name:state].volumeDown\
[$name:state].volumeUp\
 ; ; ;\
[$name:state].[$name:mute]\
<br>[$name:state] CURRENT: [$name:AV_CurrentTrackMetaData_Artist] - [$name:AV_CurrentTrackMetaData_Title] - ([$name:currentTrack_Duration])\
<br>[$name:state] NEXT: &nbsp;;&nbsp;;&nbsp;;&nbsp;;&nbsp;;&nbsp;;[$name:AV_NextTrackMetaData_Artist] - [$name:AV_NextTrackMetaData_Title] - ([$name:nextTrack_Duration])
----------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------
Neu
defmod MQTT2_RINCON_5CAAFD243CDE01400 MQTT2_DEVICE RINCON_5CAAFD243CDE01400
attr MQTT2_RINCON_5CAAFD243CDE01400 DbLogExclude .*
attr MQTT2_RINCON_5CAAFD243CDE01400 IODev mqtt2server
attr MQTT2_RINCON_5CAAFD243CDE01400 alias Wohnzimmer
attr MQTT2_RINCON_5CAAFD243CDE01400 icon audio_volume_low
attr MQTT2_RINCON_5CAAFD243CDE01400 jsonMap volume_Master:volume mute_Master:mute transportState:state
attr MQTT2_RINCON_5CAAFD243CDE01400 model sonos2mqtt_speaker
attr MQTT2_RINCON_5CAAFD243CDE01400 readingList sonos/RINCON_5CAAFD243CDE01400:.* { json2nameValue($EVENT,'',$JSONMAP) }
attr MQTT2_RINCON_5CAAFD243CDE01400 room MQTT2_DEVICE
attr MQTT2_RINCON_5CAAFD243CDE01400 setList stop:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "stop" }\
  play:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "play" }\
  pause:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "pause" }\
  toggle:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "toggle" }\
  volumeUp:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "volumeup" }\
  volumeDown:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "volumedown" }\
  volume:slider,0,1,100 sonos/RINCON_5CAAFD243CDE01400/control { "command": "volume", "input": $EVTPART1 }\
  mute:on,off { my $value = $EVTPART1 eq "on" ? "mute" : "unmute";; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "$value" } ) }\
  next:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "next" }\
  previous:noArg sonos/RINCON_5CAAFD243CDE01400/control { "command": "previous" }\
  joinGroup:textField sonos/RINCON_5CAAFD243CDE01400/control { "command": "joingroup",  "input": "$EVTPART1"}\
  leaveGroup:noArg { my $value = ReadingsVal("RINCON_5CAAFD243CDE01400","groupName","all");; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "leavegroup",  "input": "$value" } ) }\
  setAVTUri:textField sonos/RINCON_5CAAFD243CDE01400/control { "command": "setavtransporturi",  "input": "$EVTPART1"}\
  playUri:textField {fhem("set $NAME setAVTUri $EVTPART1;; sleep 1;; set $NAME play")}\
  input:Queue { my $value = $EVTPART1 eq "TV" ? "tv" : $EVTPART1 eq "Line_In" ? "line" : "queue";; qq(sonos/RINCON_5CAAFD243CDE01400/control { "command": "switchto$value" } ) }\
  notify:textField sonos/RINCON_5CAAFD243CDE01400/control { "command":"notify","input":{"trackUri":"$EVTPART2","onlyWhenPlaying":false,"timeout":10,"volume":$EVTPART1,"delayMs":700}}\
  x_raw_payload:textField { my $payload = $EVENT;;$payload =~ s/$EVTPART0 //g;; qq(sonos/RINCON_5CAAFD243CDE01400/control $payload)}\
  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");;"{}"}


Otto123

mit Bedienfelder meinst Du jetzt genau was? Das devStateIcon? Das ist im Basistemplate nicht drin. Leider habe ich noch keines was konsistent ist ;)

Das dropdown Menü sollte  komplett sein.
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

Hey zusammen,

leider ist die Zeit bisher nicht besser geworden aber anbei mal die Payloads aus dem Zweig "sonos/RINCON_123HEX:.*"...
Diese sollte ich schon ewig mal hier hochladen... :-\ Hoffe das ist soweit noch okay..

payload wenn Single und play
{"uuid":"RINCON_7828CAF427B201400","name":"Wohnzimmer","groupName":"Wohnzimmer","coordinatorUuid":"RINCON_7828CAF427B201400","currentTrack":{"Artist":"1LIVE mit Larissa Rieß und Philipp Isterewicz","AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"stream.mp3?ar-distributor=f0e2&amp;_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgxNzk3JnM9Nzg2NmYyOWMjYmFiMDQ4M2U2MjRiNDcwNWQ2ZGQ5ZWI1NGU5YjYzZGY","UpnpClass":"object.item","ItemId":"-1","ParentId":"-1","TrackUri":"x-rincon-mp3radio://https://wdr-edge-2020-fra-lg-cdn.cast.addradio.de/wdr/1live/live/mp3/128/stream.mp3?ar-distributor=f0e2&_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgxNzk3JnM9Nzg2NmYyOWMjYmFiMDQ4M2U2MjRiNDcwNWQ2ZGQ5ZWI1NGU5YjYzZGY","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},"enqueuedMetadata":{"AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"1LIVE","UpnpClass":"object.item.audioItem.audioBroadcast","ItemId":"-1","ParentId":"-1"},"transportState":"PLAYING","playmode":"NORMAL","ts":1595595401660,"volume":{"Master":11,"LF":100,"RF":100},"mute":{"Master":false,"LF":false,"RF":false}}

Payload wenn joinGroup Wohnzimmer
Master: {"uuid":"RINCON_7828CAF427B201400","name":"Wohnzimmer","groupName":"Wohnzimmer + 1","coordinatorUuid":"RINCON_7828CAF427B201400","volume":{"Master":11,"LF":100,"RF":100},"mute":{"Master":false,"LF":false,"RF":false},"ts":1595596556496,"currentTrack":{"AlbumArtUri":"http://192.168.20.70:1400/getaa?u=x-rincon-mp3radio:%2f%2fhttps:%2f%2fwdr-1live-live.icecastssl.wdr.de%2fwdr%2f1live%2flive%2fmp3%2f128%2fstream.mp3%3far-distributor%3df0e2&v=1","Title":"1LIVE","UpnpClass":"object.item","ItemId":"-1","ParentId":"-1","TrackUri":"x-rincon-mp3radio://https://wdr-1live-live.icecastssl.wdr.de/wdr/1live/live/mp3/128/stream.mp3?ar-distributor=f0e2","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},"enqueuedMetadata":{"AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"1LIVE","UpnpClass":"object.item.audioItem.audioBroadcast","ItemId":"-1","ParentId":"-1"},"transportState":"STOPPED","playmode":"NORMAL"}
Slave: {"uuid":"RINCON_7828CAF4289001400","name":"Küche","groupName":"Wohnzimmer + 1","coordinatorUuid":"RINCON_7828CAF427B201400","transportState":"PLAYING","playmode":"NORMAL","ts":1595596556496,"volume":{"Master":14,"LF":100,"RF":100},"mute":{"Master":false,"LF":false,"RF":false}}

Payload wenn Gruppe (Wohnzimmer + 1) und dann wird play gedrückt
Master: {"uuid":"RINCON_7828CAF427B201400","name":"Wohnzimmer","groupName":"Wohnzimmer + 1","coordinatorUuid":"RINCON_7828CAF427B201400","volume":{"Master":11,"LF":100,"RF":100},"mute":{"Master":false,"LF":false,"RF":false},"ts":1595596701688,"currentTrack":{"Artist":"1LIVE mit Larissa Rieß und Philipp Isterewicz","AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"stream.mp3?ar-distributor=f0e2&amp;_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgzMDE0JnM9Nzg2NmYyOWMjZTVjM2I2ZWY4ZTExOTBmNDM3OTRlNjI1NGE1YzM1OTE","UpnpClass":"object.item","ItemId":"-1","ParentId":"-1","TrackUri":"x-rincon-mp3radio://https://wdr-edge-2020-fra-lg-cdn.cast.addradio.de/wdr/1live/live/mp3/128/stream.mp3?ar-distributor=f0e2&_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgzMDE0JnM9Nzg2NmYyOWMjZTVjM2I2ZWY4ZTExOTBmNDM3OTRlNjI1NGE1YzM1OTE","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},"enqueuedMetadata":{"AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"1LIVE","UpnpClass":"object.item.audioItem.audioBroadcast","ItemId":"-1","ParentId":"-1"},"transportState":"PLAYING","playmode":"NORMAL"}
Slave: bekommt nichts mehr.

Payload wenn leaveGroup ausgeführt wird
Master: {"uuid":"RINCON_7828CAF427B201400","name":"Wohnzimmer","groupName":"Wohnzimmer","coordinatorUuid":"RINCON_7828CAF427B201400","volume":{"Master":11,"LF":100,"RF":100},"mute":{"Master":false,"LF":false,"RF":false},"ts":1595596930687,"currentTrack":{"AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"stream.mp3?ar-distributor=f0e2&amp;_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgzMDE0JnM9Nzg2NmYyOWMjZTVjM2I2ZWY4ZTExOTBmNDM3OTRlNjI1NGE1YzM1OTE","UpnpClass":"object.item","ItemId":"-1","ParentId":"-1","TrackUri":"x-rincon-mp3radio://https://wdr-edge-2020-fra-lg-cdn.cast.addradio.de/wdr/1live/live/mp3/128/stream.mp3?ar-distributor=f0e2&_art=dj0yJmlwPTkzLjIzNy4xNzMuMTQ1JmlkPWljc2N4bC1lazY3N3ZkbmImdD0xNTk1NjgzMDE0JnM9Nzg2NmYyOWMjZTVjM2I2ZWY4ZTExOTBmNDM3OTRlNjI1NGE1YzM1OTE","ProtocolInfo":"x-rincon-mp3radio:*:*:*"},"enqueuedMetadata":{"AlbumArtUri":"https://img.ardmediathek.de/standard/00/42/92/13/72/-295433861/1x1/576?mandant=ard","Title":"1LIVE","UpnpClass":"object.item.audioItem.audioBroadcast","ItemId":"-1","ParentId":"-1"},"transportState":"STOPPED","playmode":"NORMAL"}
Slave: {"uuid":"RINCON_7828CAF4289001400","name":"Küche","groupName":"Küche","coordinatorUuid":"RINCON_7828CAF4289001400","transportState":"STOPPED","playmode":"NORMAL","ts":1595596930687,"volume":{"Master":39,"LF":100,"RF":100}}

Gruß,
87Insane

andre07

ja das devStateIcon  beim ersten automatischen Anlegen der Sonosplayer war das vorhanden da war nichts mit manuell ergänzen

Otto123

Ja wie schon geschreiben devStateIcon habe ich da noch nicht drin - das ist quasi noch in Entwicklung.
Man kann,wen man will das hier nehmen, aber wahrscheinlich fehlt da wieder was für den state:
STOPPED:rc_PLAY@green:play
(pause|stop):rc_STOP@red:play
PLAYING:rc_STOP@red:stop
(TRANSITIONING|play):rc_PLAY@yellow:stop
mute:audio_volume_mute@yellow
volume:audio_volume_mid@yellow
volumeDown:audio_volume_low@yellow
volumeUp:audio_volume_high@yellow
next:rc_NEXT@yellow:stop
previous:rc_PREVIOUS@yellow:stop
(next|mute|volumeDown|volumeUp|previous|pause|volume|STOPPED|TRANSITIONING|play|stop).(false|previous|next|volumeDown|volumeUp|[0-9]+):1px-spacer
PLAYING.previous:rc_PREVIOUS:previous
PLAYING.next:rc_NEXT:next
PLAYING.volumeDown:rc_VOLDOWN:volumeDown
PLAYING.volumeUp:rc_VOLUP:volumeUp
PLAYING.false:audio_volume_high:mute+true
PLAYING.true:audio_volume_mute:mute+false
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

#368
ich habe noch etwas an der automatischen Einrichtung gebastelt. Ich beschreibe es mal später noch komplett, ich habe jetzt mal den Part der automatischen Anlage der Player gemacht.
Das soll eher eine Idee sein wie man es machen kann, sicher noch nicht im Status "fertig" :)

Vorausetzung

  • "pm2 sonos2mqtt" läuft.
  • SonosBridge Device läuft
  • XML::Simple installiert (debian libxml-simple-perl)

zwei notify machen den Job:
defmod n_configSonos1 notify global:DEFINED.MQTT2_RINCON_.* sleep 4;;set $EVTPART1 attrTemplate sonos2mqtt_speaker;;set $EVTPART1 x_raw_payload {"command": "adv-command","input": {"cmd":"GetZoneInfo","reply":"ZoneInfo"}}

defmod n_configSonos2 notify MQTT2_RINCON_.*:IPAddress:.* {\
  use XML::Simple qw(:strict);;\
  no warnings 'experimental::smartmatch';;\
  my @tv = ("S14","S11");;\
  my $url="http://$EVTPART1:1400";;\
  my $xmltext = GetFileFromURL("$url/xml/device_description.xml");;\
  my $ref = XMLin($xmltext, KeyAttr => { }, ForceArray => [ ]);;\
  my $mn=$ref->{device}{modelNumber};;\
  my $img=$ref->{device}{iconList}{icon}{url};;\
  my $icon="Sonos2mqtt_icon-$mn";;\
  my $setList=AttrVal($NAME,'setList','');;\
  fhem("setreading $NAME modelNumber $mn");;\
  fhem("\"wget -qO ./www/images/default/$icon.png $url$img\"");;\
  fhem("attr $NAME icon $icon;;sleep 4 WI;;set WEB rereadicons");;\
  if ($mn ~~ @tv) {$setList=~s/input:Queue \{/input:Queue,TV \{/};;\
  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 $NAME setList $setList")\
}

Das Erste wird getriggert wenn ein Player durch autocreate erzeugt wird.

  • Es wartet kurz und wendet das Template an.
  • Danach wird die ZoneInfo abgefragt, damit kommen einige Hardware Infos.
Das Zweite wird gettriggert wenn die ZoneInfos eintreffen (IP Adresse)

  • Es wird die Beschreibung vom Player geladen und das Model sowie die Icon URL extrahiert.
  • Das Hardware Icon wird heruntergeladen und als Icon gesetzt.
  • Damit es sichtbar wird, wird rereadicons über ein "named sleep" getriggert. (Sollte nur einmal pro Bulk geschehen)
  • Bei Playern mit TV Eingang wird setList modifiziert.
  • Die setList wird um weitere Kommandos ergänzt (hier speak).
Das kann natürlich ausgebaut werden. Vielleicht hat jemand ne Meinung oder Idee dazu.
Auf die Art kann man die vorhandenen Player jederzeit löschen:
delete MQTT2_RINCON_.*

Die MQTT Events vom Player oder ein "pm2 restart sonos2mqtt" erzeugen die Player wieder komplett automatisch.

Ich hätte das XML parsen lieber mit XML::LibXML gemacht, hab es aber nicht hinbekommen.  Ist für mich ziemlich unverständlich. Falls da jemand eine Hilfe hat.  ;)

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

#369
Zum devStateIcon:
Mir ist nach wie vor nicht klar wozu der bridgeConnected Status beim Player sein soll. Zumal der MQTT Event mMn niemals kommt wenn der Player von sich aus angelegt wird. Damit ist der Status Leer und der Event müsste irgendwie von der Bridge initiiert werden.
Warum den Status nicht in der Bridge abfragen? Und warum den Status im devStateIcon 3 mal abfragen? Hab ich da was übersehen?
Die Variante funktioniert bei mir:
{
my $groupname = ReadingsVal($name,"groupName","0");
my $sgroupname = (split(" ",ReadingsVal($name,"groupName","")))[0];
my $uuidtoname = "MQTT2_".ReadingsVal($name,"coordinatorUuid","0");
my $vol = ReadingsVal($name,"volume","");
my $img = ReadingsVal($name,"currentTrack_AlbumArtUri","");
my $trim30 = sub { return length($_[0]) < 29 ? $_[0] : substr($_[0],0,25).'...'; };
my $mystate = $name eq $uuidtoname ? ReadingsVal($name,"state","FEHLER") : ReadingsVal($uuidtoname,"state","");
my $bridgestate = ReadingsNum((devspec2array('model=sonos2mqtt_bridge'))[0],'connected',0);
my $amp = $bridgestate eq "0"
? "rot"
: $bridgestate eq "1"
? "gelb"
: "gruen";
my $playpic = $mystate eq "PLAYING"
? 'rc_PAUSE@red'
: $mystate eq "PAUSED_PLAYBACK"
? 'rc_PLAY@green'
: $mystate eq "STOPPED"
? 'rc_PLAY@green'
: $mystate eq "TRANSITIONING"
? 'rc_PLAY@blue'
: $mystate eq "set_next"
? 'rc_NEXT@blue'
: $mystate eq "set_previous"
? 'rc_PREVIOUS@blue'
: $mystate eq "set_volumeUp"
? 'rc_VOLUP@blue'
: $mystate eq "set_volumeDown"
? 'rc_VOLDOWN@blue'
: $mystate eq "set_mute"
? 'rc_MUTE@blue'
: $mystate;
my $mutecmd = ReadingsVal($name,"mute","0") eq "false"
? "true"
: "false";
my $mutepic = ReadingsVal($name,"mute","0") eq "false"
? 'rc_MUTE'
: 'rc_VOLUP';
my $show = "FEHLER";
my $currentTrack = $mystate eq "TRANSITIONING"
? "Puffern..."
: $trim30->(ReadingsVal($name,"currentTrack_Artist","FEHLER"))." - ".$trim30->(ReadingsVal($name,"currentTrack_Title","FEHLER"));
my $nextTrack = $trim30->(ReadingsVal($name,"nextTrack_Artist","FEHLER"))." - ".$trim30->(ReadingsVal($name,"nextTrack_Title","FEHLER"));
my $previouspic = 'rc_PREVIOUS';
my $nextpic = 'rc_NEXT';
my $voldownpic = 'rc_VOLDOWN';
my $voluppic = 'rc_VOLUP';

if ($bridgestate ne "2") {
$show = " ".FW_makeImage("rc_BLANK")." ";}

elsif (($mystate eq "PLAYING")
|| ($mystate eq "TRANSITIONING" )
|| ($mystate eq "set_next" )
|| ($mystate eq "set_previous" )
|| ($mystate eq "set_volumeUp" )
|| ($mystate eq "set_volumeDown" )
|| ($mystate eq "set_mute" )) {

my $shownp = ReadingsVal($name,"name","0") eq $sgroupname ? "<a href=\"/fhem?cmd.dummy=set $name previous&XHR=1\">".FW_makeImage($previouspic)."</a>
<a href=\"/fhem?cmd.dummy=set $name next&XHR=1\">".FW_makeImage($nextpic)."</a>" : "";

$show = "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>
<a href=\"/fhem?cmd.dummy=set $name volumeDown&XHR=1\">".FW_makeImage($voldownpic)."</a>
$shownp
<a href=\"/fhem?cmd.dummy=set $name volumeUp&XHR=1\">".FW_makeImage($voluppic)."</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href=\"/fhem?cmd.dummy=set $name mute $mutecmd&XHR=1\">".FW_makeImage($mutepic)."</a><br>";

if (ReadingsVal($name,"name","0") eq $sgroupname) {
$show = ReadingsVal($name,"enqueuedMetadata_UpnpClass","FEHLER") ne "object.item.audioItem.audioBroadcast"
? "$show Aktueller Track: $currentTrack<br>Nächster Track: $nextTrack"
: "$show Radio: $currentTrack";}

elsif (ReadingsVal($name,"name","0") ne $groupname) {
$show = "$show
Master: $sgroupname";}
}
else {
$show = $name eq $uuidtoname
? "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>"
: "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a><br>Master: $sgroupname";}

"<div>
<table>
  <tr>
    <td><div style='display: inline-block; margin-right: 5px; border: 1px solid lightgray; height: 4.00em; width: 4.00em; background-image: url($img);background-size: contain;'></div>
</td>
    <td>".FW_makeImage("10px-kreis-".$amp)."
$show</td>
   </tr>
</table>
</div>"
}

bzw. etwas bearbeitet für "Alle Player nachrüsten"
attr MQTT2_RINCON_.* devStateIcon {\
my $groupname = ReadingsVal($name,'groupName','0');;\
my $sgroupname = (split(' ',ReadingsVal($name,'groupName','')))[0];;\
my $uuidtoname = "MQTT2_".ReadingsVal($name,'coordinatorUuid','0');;\
my $vol = ReadingsVal($name,'volume','');;\
my $img = ReadingsVal($name,'currentTrack_AlbumArtUri','');;\
my $trim30 = sub { return length($_[0]) < 29 ? $_[0] : substr($_[0],0,25).'...';; };;\
my $mystate = $name eq $uuidtoname ? ReadingsVal($name,'state','FEHLER') : ReadingsVal($uuidtoname,'state','');;\
my $bridgestate = ReadingsNum((devspec2array('model=sonos2mqtt_bridge'))[0],'connected',0);;\
my $amp = $bridgestate == 0?'rot':$bridgestate == 1?'gelb':'gruen';;\
my $playpic = $mystate eq 'PLAYING'\
  ? 'rc_PAUSE@red'    : $mystate eq 'PAUSED_PLAYBACK'\
  ? 'rc_PLAY@green'   : $mystate eq 'STOPPED'\
  ? 'rc_PLAY@green'   : $mystate eq 'TRANSITIONING'\
  ? 'rc_PLAY@blue'    : $mystate eq 'set_next'\
  ? 'rc_NEXT@blue'    : $mystate eq 'set_previous'\
  ? 'rc_PREVIOUS@blue': $mystate eq 'set_volumeUp'\
  ? 'rc_VOLUP@blue'   : $mystate eq 'set_volumeDown'\
  ? 'rc_VOLDOWN@blue' : $mystate eq 'set_mute'\
  ? 'rc_MUTE@blue'    : 'rc_PLAY@yellow';;\
my $mutecmd = ReadingsVal($name,'mute','0') eq 'false'?'on':'off';;\
my $mutepic = $mutecmd eq 'on'? 'rc_MUTE': 'rc_VOLUP';;\
my $show = 'FEHLER';;\
my $currentTrack = $mystate eq 'TRANSITIONING'\
  ? 'Puffern...'\
  : $trim30->(ReadingsVal($name,'currentTrack_Artist','FEHLER')).' - '.$trim30->(ReadingsVal($name,'currentTrack_Title','FEHLER'));;\
my $nextTrack = $trim30->(ReadingsVal($name,'nextTrack_Artist','FEHLER')).' - '.$trim30->(ReadingsVal($name,'nextTrack_Title','FEHLER'));;\
my $previouspic = 'rc_PREVIOUS';;\
my $nextpic = 'rc_NEXT';;\
my $voldownpic = 'rc_VOLDOWN';;\
my $voluppic = 'rc_VOLUP';;\
\
if ($bridgestate ne '2') {\
$show = ' '.FW_makeImage('rc_BLANK').' '}\
\
elsif (($mystate eq 'PLAYING')\
|| ($mystate eq 'TRANSITIONING' )\
|| ($mystate eq 'set_next' )\
|| ($mystate eq 'set_previous' )\
|| ($mystate eq 'set_volumeUp' )\
|| ($mystate eq 'set_volumeDown' )\
|| ($mystate eq 'set_mute' )) {\
\
  my $shownp = ReadingsVal($name,'name','') eq $sgroupname ? "<a href=\"/fhem?cmd.dummy=set $name previous&XHR=1\">".FW_makeImage($previouspic)."</a>\
  <a href=\"/fhem?cmd.dummy=set $name next&XHR=1\">".FW_makeImage($nextpic)."</a>" : "";;\
\
  $show = "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>\
  <a href=\"/fhem?cmd.dummy=set $name volumeDown&XHR=1\">".FW_makeImage($voldownpic)."</a>\
  $shownp\
  <a href=\"/fhem?cmd.dummy=set $name volumeUp&XHR=1\">".FW_makeImage($voluppic)."</a>\
  &nbsp;;&nbsp;;&nbsp;;&nbsp;;\
  <a href=\"/fhem?cmd.dummy=set $name mute $mutecmd&XHR=1\">".FW_makeImage($mutepic)."</a><br>";;\
\
  if (ReadingsVal($name,'name','') eq $sgroupname) {\
    $show = ReadingsVal($name,'enqueuedMetadata_UpnpClass','FEHLER') ne 'object.item.audioItem.audioBroadcast'\
? "$show Aktueller Track: $currentTrack<br>Nächster Track: $nextTrack"\
: "$show Radio: $currentTrack"}\
\
elsif (ReadingsVal($name,'name','') ne $groupname) {\
  $show = "$show Master: $sgroupname"}\
}\
else {\
  $show = $name eq $uuidtoname\
  ? "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a>"\
  : "<a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($playpic)."</a><br>Master: $sgroupname"\
}\
\
"<div>\
<table>\
  <tr>\
    <td><div style='display: inline-block;; margin-right: 5px;; border: 1px solid lightgray;; height: 4.00em;; width: 4.00em;; background-image: url($img);;background-size: contain;;'></div>\
</td>\
    <td>".FW_makeImage("10px-kreis-".$amp)."\
$show</td>\
   </tr>\
</table>\
</div>"\
}


Nachtrag:
Mute funktioniert in der Version / Kombination mit dem aktuelle Template nicht. Korrigiert ;)
Fragen:
Die Abhängigkeit des devStateIcon in seiner generellen Funktion vom Status der Bridge würde ich eigentlich nicht so machen. Wozu der Status der Bridge und der Status vom Player sind doch unabhängig voneinander?
Ob man bei mute mit on und off oder besser mit true false arbeitet? Letzteres vereinfacht die Logik
Wie liefert man das jetzt alles aus? Vor allem während der Entwicklung. Extra Template für devStateIcon? Die notify in ein Template? Alles in eine Art Komforttemplate?

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

Beta-User

Was das ausliefern usw. angeht, habe ich auch nicht den zündenden Gedanken, da darf gerne auch jeder was zu sagen, der das nutzt (z.B. im ebus-template-package ist auch manches drin, das man auch anders machen könnte. Wenn das alles zu speziell ist und ggf. sinnvollerweise Perl-Code ausgelagert werden sollte, ist es mMn. einfacher, dazu eine myUtils und "Extra-Templates" auszuliefern.

Bestimmte Dinge von einer Namenswahl abhängig zu machen, sollte man aber mMn vermeiden, lieber mit devspec (model?, readingList=~, ...) arbeiten. Aber grundsätzlich sollte so eine "Generaländerung" eher vom User durchgeführt werden, und templates eher auf das einzelne Device beschränkt bleiben, alles andere wird immer mal wieder nicht verstanden (warum erzeugen bestimmte OMG-templates weitere Devices, z.B.. Dabei ist es eigentlich klar, sobald man es kurz erklärt...).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Otto123

Zitat von: Beta-User am 25 Juli 2020, 17:37:54
Bestimmte Dinge von einer Namenswahl abhängig zu machen, sollte man aber mMn vermeiden, lieber mit devspec (model?, readingList=~, ...) arbeiten.
Stimme Dir völlig zu, war ein Schnellschuss von mir und hatte keine andere Idee. Du meinst so?:
my $bridgestate = ReadingsNum((devspec2array('model=sonos2mqtt_bridge'))[0],'connected',0);Habs oben mal so geändert. ;)

Wenn ich mir define Sonos SONOS anschaue da passiert auch wesentlich mehr als ein Device ...
Warum sollte Template nicht auch ein umfangreicheres Setup erledigen?

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

andre07

Als Player wird jetzt sowas angelegt
defmod MQTT2_mqttjs_d73ad64a MQTT2_DEVICE mqttjs_d73ad64a
attr MQTT2_mqttjs_d73ad64a DbLogExclude .*
attr MQTT2_mqttjs_d73ad64a IODev mqtt2server
attr MQTT2_mqttjs_d73ad64a alias Wohnzimmer
attr MQTT2_mqttjs_d73ad64a icon audio_volume_low
attr MQTT2_mqttjs_d73ad64a jsonMap volume_Master:volume mute_Master:mute transportState:state
attr MQTT2_mqttjs_d73ad64a model sonos2mqtt_speaker
attr MQTT2_mqttjs_d73ad64a readingList sonos/RINCON_5CAAFD243CDE01400:.* { json2nameValue($EVENT,'',$JSONMAP) }
attr MQTT2_mqttjs_d73ad64a room MQTT2_DEVICE

Da dürften deine notify so auch nicht mehr funktionieren
Irgendwie scheint bei mir jetzt gar nichts mehr zu funktionieren ???
Andre

Beta-User

Zitat von: Otto123 am 26 Juli 2020, 13:28:26
Stimme Dir völlig zu, war ein Schnellschuss von mir und hatte keine andere Idee. Du meinst so?:
my $bridgestate = ReadingsNum((devspec2array('model=sonos2mqtt_bridge'))[0],'connected',0);Habs oben mal so geändert. ;)
Oben ging's mal drum, dass mehrere Devices mit einer bestimmten Namenskonvention adressiert werden, von daher war das etwas anderes, aber so in der Richtung kann man die Anregung auch verstehen. Das war btw. auch nur ein Schnellschuß aus der Hüfte.

Zitat
Wenn ich mir define Sonos SONOS anschaue da passiert auch wesentlich mehr als ein Device ...
Warum sollte Template nicht auch ein umfangreicheres Setup erledigen?
Letztlich geht es immer darum, möglichst die (vermutete) Erwartung des Users zu erfüllen. Wird dieses Ziel erreicht, ist eigentlich alles gut :) . Da v.a. Attribute aber ein "offenes System" sind, ist es andererseits recht einfach, Fehlerquellen einzubauen, bzw. Dinge, die nur unter bestimmten Rahmenbedingungen (wie eben die Beibehaltung automatisch vergebener Namen in diesem Fall). Ging nur darum, dieses "Einfallstor" möglichst zu vermeiden. (Was SONOS da macht, kenne ich nicht und kann daher nichts dazu sagen, ob das jetzt"gut" bzw. "verbesserungsfähig" gelöst ist).
Was User-Erwartungen angeht, ist meine Erfahrung leider teils die, dass selbst wenn dann mal ein entsprechender Hinweistext vorhanden und das Verhalten eigentlich (mMn.) "logisch" ist, trotzdem noch Rückfragen kommen, und wenn man was falsch machen kann, dann gibt es eben auch früher oder später jemanden, der ....

Bzgl. "Einrichtungsassistent": Was im Bereich der Sprachsteuerungs-Erweiterungen stattfindet, ist mMn. genau das - ein Einrichtungs-"Baukasten", der - abhängig von den vorhandenen Rahmenbedingungen - interaktiv das konfiguriert, was dem User in seiner konkreten Umgebung hilft.
Von daher: feel free, den Baukasten so zu nutzen! (Theoretisch könnte man darüber auch sinnvolle "global"-Attribute usw. als Ersteinrichtungshilfe abfragen usw... Die Frage bliebe allerdings, ob das wirklich hilfreich für den Einstieg in FHEM wäre - habe da starke Zweifel.)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Otto123

#374
Hallo Andre,

was da jetzt bei Dir "angelegt" wird ist für mich nicht ganz nachvollziehbar.
Die MQTT2 Device werden mit anderer Regel angelegt, weiß nicht genau warum. Eigentlich ist es doch MQTT2_<CID> Du hast keinen MQTT2_SERVER ?

Edit: Das Device was Du gezeigt hast ist doch ohne die Bridge? Hast Du keine Bridge erzeugt?!?

Ein Template wurde angewendet, aber nicht komplett - die setList fehlt komplett?

Klar damit geht von meinen notify nichts  :'(

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