diff --git a/fhem/FHEM/96_Snapcast.pm b/fhem/FHEM/96_Snapcast.pm
index 311827110..3d1d1065a 100755
--- a/fhem/FHEM/96_Snapcast.pm
+++ b/fhem/FHEM/96_Snapcast.pm
@@ -31,7 +31,7 @@ use Time::HiRes qw( gettimeofday );
use DevIo;
use JSON ();
use GPUtils qw( GP_Import );
-use List::Util qw( max min );
+use List::Util 1.45 qw( max min uniq );
#-- Run before package compilation
@@ -85,7 +85,8 @@ my %_clientmethods = (
volume => 'Client.SetVolume',
mute => 'Client.SetVolume',
stream => 'Group.SetStream',
- latency => 'Client.SetLatency'
+ latency => 'Client.SetLatency',
+ group => 'Group.SetClients'
);
=pod
@@ -262,38 +263,30 @@ sub Set {
}
return;
}
- my @ids = grep {m{\A(?:clients_.+_group)\z}xms}
- keys %{ $hash->{READINGS} };
- my @group;
- for my $sid ( @ids ) {
- my $gr = ReadingsVal($name, $sid, '');
- if ( $client eq $gr ) {
- $sid =~ m{\Aclients_(.+)_group\z}xms;
- push @group, $1;
- };
- #clients_84a93e695051_2_group a269028b-7078-210f-0e75-54acd507faaa
- }
- Log3( $hash, 5, "Snap: group members for arg. $client are @group within @ids");
- if ( @group ) {
+
+ my $grp = _getGroupMembers($hash, $client);
+ if ( @{$grp} ) {
+ my $sparm;
+ my @paramset;
if ( $opt eq 'volume' && looks_like_number($value) && $value !~ m{[+-]}x ) {
#Log3($hash,3,"SNAP: Group absolute volume command, volume: $value");
- my @paramset;
my $grvol;
- for my $sclient ( @group ) {
+ for my $sclient ( @{$grp} ) {
$grvol += ReadingsNum( $name, "clients_${sclient}_volume", 0);
}
- $grvol = int $grvol/@group;
+ $grvol = int $grvol/@{$grp};
my $change = $value - $grvol;
- for my $sclient ( @group ) {
- my $sparm->{id} = ReadingsVal( $name, "clients_${sclient}_origid", undef) // next;#_getId( $hash, $sclient) // next;
+ for my $sclient ( @{$grp} ) {
+ $sparm->{id} = ReadingsVal( $name, "clients_${sclient}_origid", undef) // next;#_getId( $hash, $sclient) // next;
my $vol = ReadingsNum( $name, "clients_${sclient}_volume", 0) + $change;
$vol = max( 0, min( 100, $vol ) );
my $muteState = ReadingsVal( $name, "clients_${sclient}_muted", 'false' );
$muteState = 'false' if $vol && ( $muteState eq 'true' || $muteState eq '1' );
$sparm->{volume}->{muted} = $muteState;
$sparm->{volume}->{percent} = $vol;
- my $payload = push @paramset, Snapcast_Encode( $hash, $_clientmethods{volume}, $sparm);
+ push @paramset, Snapcast_Encode( $hash, $_clientmethods{volume}, $sparm, 1);
}
+
return if !@paramset;
my $payload = q{[};
$payload .= join q{,},@paramset;
@@ -301,7 +294,30 @@ sub Set {
#Log3($hash,3,"SNAP: send batch $payload");
return DevIo_SimpleWrite( $hash, $payload, 2 );
}
- for my $sclient ( @group ) {
+ if ( $opt eq 'group' ) {
+ Log3( $hash, 3, "Snap: $opt command received for @{$grp}" );
+ my $opt2 = shift @param;
+ my $clnt = shift @param // return 'group commands require two additional arguments!';
+ $clnt = _getId( $hash, $clnt) // $clnt;
+ $sparm->{id} = $client; #needs group2id function as well
+
+ if ( $opt2 eq 'name' ) {
+ $sparm->{name} = $clnt;
+
+ return DevIo_SimpleWrite( $hash, Snapcast_Encode( $hash, 'Group.SetName', $sparm), 2 );
+ }
+ push @{$grp}, $clnt if $opt2 eq 'add';
+ my @grIds;
+ for ( @{$grp} ) {
+ push @grIds, _getId( $hash, $_) // $_;
+ }
+ @grIds = grep { $_ !~ m{\A$clnt\z}x } @grIds if $opt2 eq 'remove';
+ @grIds = uniq(@grIds);
+ $sparm->{clients} = \@grIds;
+ return DevIo_SimpleWrite( $hash, Snapcast_Encode( $hash, 'Group.SetClients', $sparm), 2 );
+ }
+
+ for my $sclient ( @{$grp} ) {
$sclient =~ s{:}{}gx;
$sclient =~ s{[#]}{_}gx;
my $res = _setClient( $hash, $sclient, $opt, $value );
@@ -316,6 +332,20 @@ sub Set {
return "$opt not implemented yet!";
}
+=pod
+
+ For client type devices, you may use a single group id as argument to add the client to the given group or the keyword remove
to singularize that client.
+ Options for server type devices:
+
name <group id> <new name>
add <client> <group id>
add that client to the given groupremove <client> <group id>
remove
to singularize that client.
+ Options for server type devices:
+ <group id> name <new name>
<group id> add <client>
add that client to the given group<group id> remove <client>