Sonos Slave Devices fast wie Master Devices behandeln

Begonnen von Loredo, 06 August 2016, 12:43:06

Vorheriges Thema - Nächstes Thema

Loredo

Hallo Reinerlein,

ich möchte gerne, dass die Slave Devices sich größtenteils wie ihre Master Devices "anfühlen", damit ich einfach irgendein Mitglied der Gruppe bedienen kann und trotzdem die aktuellen Abspiel-Infos richtig angezeigt bekomme.
Da die Readings der Slave Devices momentan viele Infos nicht mit dem Master Device abgleichen, mache ich das manuell am Modul vorbei.

Dafür habe ich zunächst folgende Readings an allen Sonos Geräten gesetzt:


attr Sonos_.* event-on-change-reading Volume,presence,transportState,Mute,infoSummarize1,infoSummarize2,stateAV,currentAlbum,currentAlbumArtURL
attr Sonos_.* event-on-update-reading LastActionResult,somethingChanged
attr Sonos_.* generateSomethingChangedEvent 1
attr Sonos_.* generateVolumeEvent 1


Anschließend habe ich ein DOIF angelegt, welches eine Funktion aus meiner myUtils aufruft:


define di_Sonos_UpdateSlavePlayer DOIF (["^Sonos_:^somethingChanged"])({mySonosUpdateSlavePlayer("$DEVICE")})


So sieht schließlich die Erweiterungsfunktion in 99_myUtils.pm aus:


sub mySonosUpdateSlavePlayer($) {
    my ($name) = @_;
    my $MasterPlayer = ReadingsVal($name, "MasterPlayer", $name);
    my $SlavePlayers = ReadingsVal($name, "SlavePlayer", "[]");
    my $IsMaster = ReadingsVal($name, "IsMaster", "0");

   return if ($IsMaster eq "0" || $MasterPlayer ne $name );

   foreach my $SlavePlayer ( @{ eval $SlavePlayers } ) {
      my $SlavePlayerMaster = ReadingsVal($SlavePlayer, "MasterPlayer", $SlavePlayer);
      next if($SlavePlayerMaster ne $MasterPlayer);

      Log3 $name, 4, "SONOSPLAYER $name SonosUpdateSlavePlayer: Syncing readings to $SlavePlayer";

      readingsBeginUpdate( $defs{$SlavePlayer} );

      # sync all current* and next* readings
      foreach my $reading ( keys %{ $defs{$SlavePlayerMaster}{READINGS} } ) {
         next if ($reading !~ /^(current|next).*/);
         my $vn = ReadingsVal($SlavePlayerMaster, $reading, "");
         my $vo = ReadingsVal($defs{$SlavePlayer}, $reading, "");
         readingsBulkUpdate( $defs{$SlavePlayer}, $reading, $vn ) if $vn ne $vo;
      }

      # explicitly sync some additional readings
      foreach my $reading (
         "GroupMute",
         "GroupVolume",
         "Repeat",
         "RepeatOne",
         "Shuffle",
         "infoSummarize1",
         "infoSummarize2",
         "numberOfTracks",
      ) {
         my $vn = ReadingsVal($SlavePlayerMaster, $reading, "");
         my $vo = ReadingsVal($defs{$SlavePlayer}, $reading, "");
         readingsBulkUpdate( $defs{$SlavePlayer}, $reading, $vn ) if $vn ne $vo;
      }

      readingsEndUpdate( $defs{$SlavePlayer}, 1);

      #SONOS_ProcessInfoSummarize($SlavePlayer, \$defs{$SlavePlayer}, 'InfoSummarize1', 1);
      #SONOS_ProcessInfoSummarize($SlavePlayer, \$defs{$SlavePlayer}, 'InfoSummarize2', 1);
      #SONOS_ProcessInfoSummarize($SlavePlayer, \$defs{$SlavePlayer}, 'InfoSummarize3', 1);
      #SONOS_ProcessInfoSummarize($SlavePlayer, \$defs{$SlavePlayer}, 'InfoSummarize4', 1);

   }
}


Das funktioniert auch hervorragend bis auf einige Kleinigkeiten:


       
  • GroupMute und GroupVolume erzeugen wohl keinen Trigger für somethingChanged. Folglich wird meine Funktion bei einer Änderung der Gruppenlautstärke nicht aufgerufen und wenn ich dann an einem anderen Gerät als dem Master Gerät die Gruppenlautstärke mittels GroupVolume verändere, wird ein falscher Wert verwendet und die Lautstärke der Geräte wird nicht synchron verändert (selbes für GroupMute). Könntest du auch bei einer Änderung von GroupVolume und GroupMute am Master Device somethingChanged triggern lassen?
  • infoSummarize wird nicht individuell für das jeweilige Device berechnet, weshalb es bei den Default-Werten auch nur Sinn macht infoSummarize1 und infoSummarize2 vom Master Gerät zu übernehmen. Ich habe SONOS_ProcessInfoSummarize() nicht dazu bewegen können, dass ich es aus meiner Funktion direkt aufrufe. Gibts da eine Möglichkeit?
Gruß
Julian



PS: Ich nehme an es besteht keine Hoffnung, dass du solch einen Sync direkt mit ins Modul einbaust und man sich die zusätzlichen Events und Trigger sparen könnte. Oder doch? ;-)
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Loredo

#1
Ok, die Readings explizit triggern zu lassen hilft natürlich auch, ist aber nicht so schön:



attr Sonos_.* event-on-change-reading Volume,presence,transportState,Mute,currentAlbum,currentAlbumArtURL,GroupVolume,GroupMute,Repeat,RepeatOne,Shuffle,numberOfTracks,infoSummarize1,infoSummarize2,stateAV




define di_Sonos_UpdateSlavePlayer DOIF (["^Sonos_:^somethingChanged"] or ["^Sonos_:^(GroupVolume|GroupMute|Repeat|RepeatOne|Shuffle|numberOfTracks)"])({jpSonosUpdateSlavePlayer("$DEVICE")})



Dabei ist mir nun aufgefallen, dass GroupVolume nicht so arbeitet wir der Sonos eigene Controller.
Wenn ich zwei unterschiedliche Lautstärken an Master und Slave Geräten eingestellt habe, verändert der Sonos Controller die Lautstärke jedes Gerätes relativ zur Gruppenlautstärke. Das Fhem SONOS Modul hingegen setzt für alle Gruppenmitglieder einfach die gleiche Lautstärke. Ist es auch möglich, dass die Gruppenlautstärke hier relativ für jedes Slave Gerät gesetzt wird anstatt explizit?


Momentan sind diese beiden Befehle wohl identisch (zumindest von ihrem Verhalten):



# Vorher - Sonos_Living_Room Volume: 10; Sonos_Kitchen Volume: 5; GroupVolume: 13(int(10+5/2+0.5))
# Nachher - Sonos_Living_Room Volume: 15; Sonos_Kitchen Volume: 15; GroupVolume: 15
# Erwartet - Sonos_Living_Room Volume: 10; Sonos_Kitchen Volume: 10; GroupVolume: <15
set Sonos_Living_Room GroupVolume 15


# Vorher - Sonos_Living_Room Volume: 10; Sonos_Kitchen Volume: 5; GroupVolume: 13(int(10+5/2+0.5))
# Nachher - Sonos_Living_Room Volume: 15; Sonos_Kitchen Volume: 15; GroupVolume: 15
# Erwartet - Sonos_Living_Room Volume: 15; Sonos_Kitchen Volume: 15; GroupVolume: 15
set Sonos_Living_Room,Sonos_Kitchen Volume 15



Daher stellt sich die Frage: Ist der GroupVolume Befehl wirklich nur eine Vereinfachung oder ist da ein Bug und er sollte so funktionieren wie der Sonos Controller es tut? Vermutlich rechnet das Sonos Master Gerät oder der Controller das GroupVolume irgendwie aus und man müsste das auch so im SONOS Modul nachbilden?
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER