diff --git a/21_HEOSGroup.pm b/21_HEOSGroup.pm index 2fbc5e1..59d9dbd 100644 --- a/21_HEOSGroup.pm +++ b/21_HEOSGroup.pm @@ -37,7 +37,7 @@ use JSON qw(decode_json); use Encode qw(encode_utf8); -my $version = "0.1.70"; +my $version = "0.1.71"; @@ -218,12 +218,9 @@ sub HEOSGroup_Notify($$) { my $events = deviceEvents($dev,1); - #print "notify ####################################################\n".Dumper($events); - return if( !$events ); readingsBeginUpdate($hash); - #my %playerEevents = map { my ( $key, $value ) = split /:\s/; $value =~ s/^\s+//; ( $key, $value ) } @$events; my %playerEevents = map { my ( $key, $value ) = split /:\s/; ( $key, $value ) } @$events; foreach my $key ( keys %playerEevents ) { @@ -263,19 +260,19 @@ sub HEOSGroup_Set($$@) { $action = "state=$args[0]"; } elsif( $cmd eq 'volume' ) { - return "usage: volume 0-100" if( @args != 1 ); + return "usage: volume 0-100" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 100 || $args[0] < 0 ); $heosCmd = 'setGroupVolume'; $action = "level=$args[0]"; } elsif( $cmd eq 'volumeUp' ) { - return "usage: volumeUp 0-10" if( @args != 1 ); + return "usage: volumeUp 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 0 ); $heosCmd = 'GroupVolumeUp'; $action = "step=$args[0]"; } elsif( $cmd eq 'volumeDown' ) { - return "usage: volumeDown 0-10" if( @args != 1 ); + return "usage: volumeDown 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 0 ); $heosCmd = 'groupVolumeDown'; $action = "step=$args[0]"; @@ -286,7 +283,7 @@ sub HEOSGroup_Set($$@) { $heosCmd = 'createGroup'; $string = "pid=$gid"; - } elsif( grep { $_ =~ /\Q$cmd\E/ } ("play", "stop", "pause", "next", "prev", "channel", "channelUp", "channelDown", "playlist" ) ) { + } elsif( grep { $_ eq $cmd } ("play", "stop", "pause", "next", "prev", "channel", "channelUp", "channelDown", "playlist" ) ) { #ab hier Playerbefehle emuliert $string = "pid=$gid"; @@ -334,34 +331,57 @@ sub HEOSGroup_Set($$@) { $heosCmd = 'playPrev'; - } elsif ( $cmd eq 'channel' ) { - - $favoritcount = scalar(@{$hash->{IODev}{helper}{favorites}}) if ( defined $hash->{IODev}{helper}{favorites} ); - return "usage: channel 1-$favoritcount" if( @args != 1 ); - - $heosCmd = 'playPresetStation'; - $action = "preset=$args[0]"; - - } elsif( $cmd eq 'channelUp' ) { - return "usage: channelUp" if( @args != 0 ); + } elsif ( $cmd =~ /channel/ ) { + + my $favorit = ReadingsVal($name,"channel", 1); $favoritcount = scalar(@{$hash->{IODev}{helper}{favorites}}) if ( defined $hash->{IODev}{helper}{favorites} ); $heosCmd = 'playPresetStation'; - $favorit = ReadingsVal($name,"channel", 0) + 1; - $favorit = $favoritcount if ( $favorit > $favoritcount); - $action = "preset=".$favorit; - } elsif( $cmd eq 'channelDown' ) { - return "usage: channelDown" if( @args != 0 ); - - $heosCmd = 'playPresetStation'; - $favorit = ReadingsVal($name,"channel", 0) - 1; - $favorit = 1 if ($favorit <= 0); - $action = "preset=".$favorit; + if ( $cmd eq 'channel' ) { + return "usage: $cmd 1-$favoritcount" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > $favoritcount || $args[0] < 1); + + $action = "preset=$args[0]"; + + } elsif( $cmd eq 'channelUp' ) { + return "usage: $cmd" if( @args != 0 ); + + ++$favorit; + if ( $favorit > $favoritcount ) { + if ( AttrVal($name, 'channelring', 0) == 1 ) { + + $favorit = 1; + + } else { + + $favorit = $favoritcount; + + } + } + + $action = "preset=".$favorit; + + } elsif( $cmd eq 'channelDown' ) { + return "usage: $cmd" if( @args != 0 ); + + --$favorit; + if ( $favorit <= 0 ) { + if ( AttrVal($name, 'channelring', 0) == 1 ) { + + $favorit = $favoritcount; + + } else { + + $favorit = 1; + } + } + + $action = "preset=".$favorit; + } } elsif ( $cmd =~ /Playlist/ ) { - my @cids = map { $_->{cid} } grep { $_->{name} =~ /$args[0]/i } (@{ $hash->{IODev}{helper}{playlists} }); + my @cids = map { $_->{cid} } grep { $_->{name} =~ /\Q$args[0]\E/i } (@{ $hash->{IODev}{helper}{playlists} }); if ( scalar @args == 1 && scalar @cids > 0 ) { if ( $cmd eq 'playPlaylist' ) { @@ -468,7 +488,7 @@ sub HEOSGroup_WriteReadings($$) { my $name = $hash->{NAME}; - Log3 $name, 3, "HEOSGroup ($name) - processing data to write readings"; + Log3 $name, 4, "HEOSGroup ($name) - processing data to write readings"; ############################ #### Aufbereiten der Daten soweit nötig (bei Events zum Beispiel) my $readingsHash = HEOSGroup_PreProcessingReadings($hash,$decode_json) @@ -556,7 +576,7 @@ sub HEOSGroup_PreProcessingReadings($$) { } else { - Log3 $name, 3, "HEOSGroup ($name) - no match found"; + Log3 $name, 4, "HEOSGroup ($name) - no match found"; return undef; } diff --git a/21_HEOSMaster.pm b/21_HEOSMaster.pm index bca4624..487e50e 100644 --- a/21_HEOSMaster.pm +++ b/21_HEOSMaster.pm @@ -54,7 +54,7 @@ eval "use IO::Socket::Multicast;1" or $missingModulNet .= "IO::Socket::Multicast -my $version = "0.1.70"; +my $version = "0.1.71"; my %heosCmds = ( 'enableChangeEvents' => 'system/register_for_change_events?enable=', @@ -134,8 +134,8 @@ sub HEOSMaster_GetInputs($); sub HEOSMaster_GetMusicSources($); sub HEOSMaster_GetPlaylists($); sub HEOSMaster_GetServers($); -sub HEOSMaster_Hexdump; sub HEOSMaster_MakePlayLink($$$$); +sub HEOSMaster_MakeImage($$); @@ -282,59 +282,52 @@ sub HEOSMaster_Set($@) { if($cmd eq 'reopen') { - return "usage: reopen" if( @args != 0 ); + HEOSMaster_ReOpen($hash); return undef; } elsif($cmd eq 'getPlayers') { - return "usage: getPlayers" if( @args != 0 ); + $heosCmd = 'getPlayers'; $action = undef; } elsif($cmd eq 'getGroups') { - return "usage: getGroups" if( @args != 0 ); + $heosCmd = 'getGroups'; $action = undef; } elsif($cmd eq 'enableChangeEvents') { - return "usage: enableChangeEvents" if( @args != 1 ); + $heosCmd = $cmd; $action = $args[0]; } elsif($cmd eq 'checkAccount') { - return "usage: checkAccount" if( @args != 0 ); + $heosCmd = $cmd; $action = undef; } elsif($cmd eq 'signAccount') { - return "usage: signAccountIn" if( @args != 1 ); + return "please set account informattion first" if(AttrVal($name,'heosUsername','none') eq 'none'); $heosCmd = $cmd . $args[0]; $action = 'un='. AttrVal($name,'heosUsername','none') . '&pw=' . HEOSMaster_ReadPassword($hash) if($args[0] eq 'In'); } elsif($cmd eq 'password') { - return "usage: password" if( @args != 1 ); + return HEOSMaster_StorePassword( $hash, $args[0] ); } elsif($cmd eq 'reboot') { - return "usage: reboot" if( @args != 0 ); - return HEOSMaster_StorePassword( $hash, $args[0] ); - ################################################### - ### Dieser Menüpunkt ist nur zum testen - - } elsif($cmd eq 'eventSend') { - return "usage: eventSend" if( @args != 0 ); - HEOSMaster_send($hash); - return undef; - ################################################### + + $heosCmd = $cmd; + $action = undef; } else { @@ -507,7 +500,8 @@ sub HEOSMaster_ProcessRead($$) { $hash->{LAST_RECV} = time(); Log3 $name, 5, "HEOSMaster ($name) - Decoding JSON message. Length: " . length($json) . " Content: " . $json; - my $obj = JSON->new->utf8(0)->decode($json); + #my $obj = JSON->new->utf8(0)->decode($json); Änderung unter großem Vorbehalt wegen Sorge was Umlaute an geht!!! + my $obj = decode_json($json); if(defined($obj->{heos})) { @@ -533,6 +527,7 @@ sub HEOSMaster_ResponseProcessing($$) { my ($hash,$json) = @_; my $name = $hash->{NAME}; my $decode_json; + my %message; Log3 $name, 5, "HEOSMaster ($name) - JSON String: $json"; @@ -546,7 +541,7 @@ sub HEOSMaster_ResponseProcessing($$) { unless(ref($decode_json) eq "HASH"); return Log3 $name, 4, "HEOSMaster ($name) - heos worked" - if( $decode_json->{heos}{message} =~ /command\sunder\sprocess/ ); + if( defined($decode_json->{heos}{message}) && $decode_json->{heos}{message} =~ /command\sunder\sprocess/ ); if( defined($decode_json->{heos}{result}) or $decode_json->{heos}{command} =~ /^system/ ) { @@ -554,10 +549,30 @@ sub HEOSMaster_ResponseProcessing($$) { Log3 $name, 4, "HEOSMaster ($name) - call Sub HEOSMaster_WriteReadings"; } - my %message = map { my ( $key, $value ) = split "="; $key => $value } split('&', $decode_json->{heos}{message}); + if( defined($decode_json->{heos}{message}) ) { - return Log3 $name, 4, "HEOSMaster ($name) - general error ID $message{eid} - $message{text}" - if( defined($decode_json->{heos}{result}) && $decode_json->{heos}{result} =~ /fail/ ); + %message = map { my ( $key, $value ) = split "="; $key => $value } split('&', $decode_json->{heos}{message}); + + return Log3 $name, 4, "HEOSMaster ($name) - general error ID $message{eid} - $message{text}" + if( defined($message{eid}) ); + } + + #Player neu einlesen + if( $decode_json->{heos}{command} =~ /^event\/players_changed/ ) { + + HEOSMaster_Write($hash,'getPlayers',undef,undef); + return Log3 $name, 4, "HEOSMaster ($name) - player changed"; + } + + #Gruppen neu einlesen + if( $decode_json->{heos}{command} =~ /^event\/groups_changed/ ) { + + + HEOSMaster_Write($hash,'getGroups',undef,undef); + #Player neu einlesen da Stereopaare sonst nicht erkannt werden + InternalTimer( gettimeofday()+3, 'HEOSMaster_GetPlayers', $hash, 0 ); + return Log3 $name, 4, "HEOSMaster ($name) - groups changed"; + } #Quellen neu einlesen if( $decode_json->{heos}{command} =~ /^event\/sources_changed/ ) { @@ -566,13 +581,6 @@ sub HEOSMaster_ResponseProcessing($$) { return Log3 $name, 4, "HEOSMaster ($name) - source changed"; } - #Player neu einlesen - if( $decode_json->{heos}{command} =~ /^event\/players_changed/ ) { - - HEOSMaster_Write($hash,'getPlayers',undef,undef); - return Log3 $name, 4, "HEOSMaster ($name) - player changed"; - } - #User neu einlesen if( $decode_json->{heos}{command} =~ /^event\/user_changed/ ) { @@ -580,14 +588,6 @@ sub HEOSMaster_ResponseProcessing($$) { return Log3 $name, 4, "HEOSMaster ($name) - user changed"; } - #Gruppen neu einlesen - if( $decode_json->{heos}{command} =~ /^event\/groups_changed/ ) { - - #InternalTimer( gettimeofday()+5, 'HEOSMaster_GetGroups', $hash, 0 ); - HEOSMaster_Write($hash,'getGroups',undef,undef); - return Log3 $name, 4, "HEOSMaster ($name) - groups changed"; - } - #Queue für Player neu einlesen if ( $decode_json->{heos}{command} =~ /^event\/player_queue_changed/ ) { @@ -668,7 +668,43 @@ sub HEOSMaster_ResponseProcessing($$) { my $start = $message{range} + $message{returned}; - if( $message{sid} eq '1028' ) { + if( $message{sid} eq '1024' ) { + + #Lokal einlesen + push( @{$hash->{helper}{sources}}, map { $_->{name} .= " USB" if ( $_->{sid} < 0 ); $_ } (@{$decode_json->{payload}}) ); + + foreach my $source (@{$hash->{helper}{sources}}) { + + HEOSMaster_Write($hash,'searchCriteria','sid='.$source->{sid},undef); + Log3 $name, 3, "HEOSMaster ($name) - call Browser for searchCriteria for sid $source->{sid}"; + } + + } elsif( $message{sid} eq '1025' ) { + + #Playlisten einlesen + $hash->{helper}{playlists} = [] if ( $message{range} == 0 ); + push( @{$hash->{helper}{playlists}}, (@{$decode_json->{payload}}) ); + + } elsif( $message{sid} eq '1026' ) { + + #History einlesen + $hash->{helper}{history} = [] if ( $message{range} == 0 ); + push( @{$hash->{helper}{history}}, (@{$decode_json->{payload}}) ); + + } elsif( $message{sid} eq '1027' ) { + + #Inputs einlesen + $hash->{helper}{aux} = [] if ( $message{range} == 0 ); + push( @{$hash->{helper}{aux}}, (@{$decode_json->{payload}}) ); + + foreach my $item (@{$decode_json->{payload}}) { + + + HEOSMaster_Write($hash,'browseSource',"sid=$item->{sid}",undef); + Log3 $name, 3, "HEOSMaster ($name) - call Browser for Input with sid $item->{sid}"; + } + + } elsif( $message{sid} eq '1028' ) { #Favoriten einlesen $hash->{helper}{favorites} = [] if ( $message{range} == 0 ); @@ -685,46 +721,10 @@ sub HEOSMaster_ResponseProcessing($$) { } } - } elsif( $message{sid} eq '1026' ) { - - #History einlesen - $hash->{helper}{history} = [] if ( $message{range} == 0 ); - push( @{$hash->{helper}{history}}, (@{$decode_json->{payload}}) ); - - } elsif( $message{sid} eq '1025' ) { - - #Playlisten einlesen - $hash->{helper}{playlists} = [] if ( $message{range} == 0 ); - push( @{$hash->{helper}{playlists}}, (@{$decode_json->{payload}}) ); - - } elsif( $message{sid} eq '1027' ) { - - #Inputs einlesen - $hash->{helper}{aux} = [] if ( $message{range} == 0 ); - push( @{$hash->{helper}{aux}}, (@{$decode_json->{payload}}) ); - - foreach my $item (@{$decode_json->{payload}}) { - - #$hash->{helper}{aux}{$item->{sid}} = $item->{name}; - HEOSMaster_Write($hash,'browseSource',"sid=$item->{sid}",undef); - Log3 $name, 3, "HEOSMaster ($name) - call Browser for Input with sid $item->{sid}"; - } - - } elsif( $message{sid} eq '1024' ) { - - #Lokal einlesen - push( @{$hash->{helper}{sources}}, map { $_->{name} .= " USB" if ( $_->{sid} < 0 ); $_ } (@{$decode_json->{payload}}) ); - - foreach my $source (@{$hash->{helper}{sources}}) { - - HEOSMaster_Write($hash,'searchCriteria','sid='.$source->{sid},undef); - Log3 $name, 3, "HEOSMaster ($name) - call Browser for searchCriteria for sid $source->{sid}"; - } - } else { #AUX Eingang des Player im Player abspeichern - if ( defined $hash->{helper}{aux} && grep( $_->{sid} =~ /$message{sid}/, (@{ $hash->{helper}{aux} }) ) ) { + if ( defined $hash->{helper}{aux} && grep( $_->{sid} =~ /^$message{sid}$/, (@{ $hash->{helper}{aux} }) ) ) { my $code = abs($message{sid}); $code = $hash->{NAME} ."-". $code if( defined($hash->{NAME}) ); @@ -783,16 +783,6 @@ sub HEOSMaster_ResponseProcessing($$) { @list = (@{$hash->{helper}{favorites}}); - } elsif ( $message{sid} eq "1029" ) { - - my $code = abs($hash->{helper}{blocking}{$idx}{pid}); - $code = $hash->{NAME} ."-". $code if( defined($hash->{NAME}) ); - - if( my $phash = $modules{HEOSPlayer}{defptr}{$code} ) { - - @list = (@{$phash->{helper}{queue}}); - - } } else { @list = (@{$hash->{helper}{media}}); @@ -867,10 +857,10 @@ sub HEOSMaster_ResponseProcessing($$) { my $ret = ''; $ret .= sprintf( "%-35s %-10s %s\n", 'Fav', 'type', 'title' ); - foreach my $item (@{ $hash->{helper}{searchresult}}) { + #foreach my $item (@{ $hash->{helper}{searchresult}}) { - $ret .= HEOSMaster_MakePlayLink($hash->{helper}{blocking}{name}, 'input', $message{sid}, $item, sprintf( "%-35s %-10s %s\n", "x", $item->{type}, $item->{name} ) ); - } + # $ret .= HEOSMaster_MakePlayLink($hash->{helper}{blocking}{name}, 'input', $message{sid}, $item, sprintf( "%-35s %-10s %s\n", "x", $item->{type}, $item->{name} ) ); + #} $ret .= "\n\n"; @@ -968,7 +958,7 @@ sub HEOSMaster_ResponseProcessing($$) { if ( $start < $message{count} ) { HEOSMaster_Write($hash,'getQueue',"pid=$message{pid}&range=$start,".($start + 100),undef); - Log3 $name, 3, "HEOSMaster ($name) - call getQueue for player pid $message{pid} next Range from $message{returned}"; + Log3 $name, 4, "HEOSMaster ($name) - call getQueue for player pid $message{pid} next Range from $start"; } else { @@ -977,8 +967,8 @@ sub HEOSMaster_ResponseProcessing($$) { if( my $phash = $modules{HEOSPlayer}{defptr}{$code} ) { - $phash->{helper}{queue} = $hash->{helper}{queue}; - delete $hash->{helper}{queue}; + $phash->{helper}{queue} = $hash->{helper}{queue}{$message{pid}}; + delete $hash->{helper}{queue}{$message{pid}}; } $json = '{"heos": {"command": "event/player_queue_changed", "message": "pid='.$message{pid}.'"}}'; @@ -1108,7 +1098,7 @@ sub HEOSMaster_PreProcessingReadings($$) { $buffer{'enableChangeEvents'} = $message{enable}; } elsif ( $decode_json->{heos}{command} eq 'system/check_account' or $decode_json->{heos}{command} eq 'system/sign_in' ) { - if ( exists $message{signed_out} ) { + if ( exists $message{signed_out} || exists $message{eid} ) { $buffer{'heosAccount'} = "signed_out"; @@ -1326,7 +1316,6 @@ sub HEOSMaster_MakePlayLink($$$$) { my $xcmd; my $xtext = $message->{sid}; - #return $txt if( !$FW_ME ); if ( (exists $item->{playable} && $item->{playable} eq "yes") || exists $item->{qid} ) { @@ -1375,29 +1364,16 @@ sub HEOSMaster_MakePlayLink($$$$) { $xtext .= ','.$item->{qid}; } - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; + $xcmd = "FW_cmd('$FW_ME$FW_subdir?XHR=1&$xcmd')"; return '
  • '.sprintf( "%-35s %-15s %s", $xtext, $item->{type}, $item->{name} )."
  • \n"; - #$FW_ME$FW_subdir } -sub HEOSMaster_Hexdump { - my $str = ref $_[0] ? ${$_[0]} : $_[0]; +sub HEOSMaster_MakeImage($$) { - return "[ZERO-LENGTH STRING]\n" unless length $str; + my ($url, $size) = @_; + my $ret .= "\n"; - # split input up into 16-byte chunks: - my @chunks = $str =~ /([\0-\377]{1,16})/g; - # format and print: - my @print; - for (@chunks) { - my $hex = unpack "H*", $_; - tr/ -~/./c; # mask non-print chars - $hex =~ s/(..)(?!$)/$1 /g; # insert spaces in hex - # make sure our hex output has the correct length - $hex .= ' ' x ( length($hex) < 48 ? 48 - length($hex) : 0 ); - push @print, "$hex $_\n"; - } - wantarray ? @print : join '', @print; + return $ret; } diff --git a/21_HEOSPlayer.pm b/21_HEOSPlayer.pm index 6ad29fc..46af231 100644 --- a/21_HEOSPlayer.pm +++ b/21_HEOSPlayer.pm @@ -38,7 +38,7 @@ use Encode qw(encode_utf8); use URI::Escape; use Data::Dumper; -my $version = "0.1.70"; +my $version = "0.1.71"; @@ -60,7 +60,6 @@ sub HEOSPlayer_GetPlayMode($); sub HEOSPlayer_GetVolume($); sub HEOSPlayer_Get($$@); sub HEOSPlayer_GetMute($); -sub HEOSPlayer_Hexdump; @@ -82,6 +81,7 @@ sub HEOSPlayer_Initialize($) { $hash->{AttrList} = "IODev ". "disable:1 ". "mute2play:1 ". + "channelring:1 ". $readingFnAttributes; foreach my $d(sort keys %{$modules{HEOSPlayer}{defptr}}) { @@ -149,6 +149,7 @@ sub HEOSPlayer_Define($$) { InternalTimer( gettimeofday()+int(rand(8)), "HEOSPlayer_GetPlayMode", $hash, 0 ); InternalTimer( gettimeofday()+int(rand(10)), "HEOSPlayer_GetVolume", $hash, 0 ); InternalTimer( gettimeofday()+int(rand(12)), "HEOSPlayer_GetMute", $hash, 0 ); + InternalTimer( gettimeofday()+int(rand(14)), "HEOSPlayer_GetQueue", $hash, 0 ); } else { @@ -157,7 +158,8 @@ sub HEOSPlayer_Define($$) { InternalTimer( gettimeofday()+15+int(rand(6)), "HEOSPlayer_GetNowPlayingMedia", $hash, 0 ); InternalTimer( gettimeofday()+15+int(rand(8)), "HEOSPlayer_GetPlayMode", $hash, 0 ); InternalTimer( gettimeofday()+15+int(rand(10)), "HEOSPlayer_GetVolume", $hash, 0 ); - InternalTimer( gettimeofday()+15+int(rand(12)), "HEOSPlayer_GetMute", $hash, 0 ); + InternalTimer( gettimeofday()+15+int(rand(12)), "HEOSPlayer_GetMute", $hash, 0 ); + InternalTimer( gettimeofday()+15+int(rand(14)), "HEOSPlayer_GetQueue", $hash, 0 ); } readingsBeginUpdate($hash); @@ -242,60 +244,41 @@ sub HEOSPlayer_Get($$@) { if ( $param eq '' ) { - my $xcmd; - my $ret = "Quellen\n"; - $ret .= sprintf( "%-35s %-15s %s\n", 'key', 'type', 'title' ); + my $ret = "Musik\n"; + #$ret .= sprintf( "%-35s %-15s %s\n", 'key', 'type', 'title' ); foreach my $item (@{ $hash->{IODev}{helper}{sources}}) { - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls '.$item->{sid}); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", $item->{sid}, $item->{type}, $item->{name} )."
  • \n"; + #$ret .= '
  • '.sprintf( "%-35s %-15s %s", $item->{sid}, $item->{type}, $item->{name} )."
  • \n"; + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, $item->{sid}, $item->{type}, $item->{name}); } - if ( defined $hash->{IODev}{helper}{playlists} ) { - - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls 1025'); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", '1025', "heos_service", "Playlist" )."
  • \n"; - } + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1025", "heos_service", "Playlist") + if ( defined $hash->{IODev}{helper}{playlists} ); + #https://production.ws.skyegloup.com:443/media/images/service/logos/musicsource_logo_playlists.png - if ( defined $hash->{IODev}{helper}{history} ) { - - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls 1026'); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", '1026', "heos_service", "Verlauf" )."
  • \n"; - } + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1026", "heos_service", "Verlauf") + if ( defined $hash->{IODev}{helper}{history} ); + #https://production.ws.skyegloup.com:443/media/images/service/logos/musicsource_logo_history.png - if ( defined $hash->{IODev}{helper}{aux} ) { - - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls 1027'); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", '1027', "heos_service", "Eingänge" )."
  • \n"; - } + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1027", "heos_service", "Eingänge") + if ( defined $hash->{IODev}{helper}{aux} ); + #https://production.ws.skyegloup.com:443/media/images/service/logos/musicsource_logo_aux.png - if ( defined $hash->{IODev}{helper}{favorites} ) { - - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls 1028'); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", '1028', "heos_service", "Favoriten" )."
  • \n"; - } + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1028", "heos_service", "Favoriten") + if ( defined $hash->{IODev}{helper}{favorites} ); + #https://production.ws.skyegloup.com:443/media/images/service/logos/musicsource_logo_favorites.png - if ( defined $hash->{helper}{queue} ) { - - $xcmd = 'cmd'.uri_escape('=get '.$hash->{NAME}.' ls 1029'); - $xcmd = "FW_cmd('/fhem?XHR=1&$xcmd')"; - $ret .= '
  • '.sprintf( "%-35s %-15s %s", '1029', "heos_service", "Warteschlange" )."
  • \n"; - } + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1029", "heos_service", "Warteschlange") + if ( defined $hash->{helper}{queue} ); + #https://production.ws.skyegloup.com:443/media/images/service/logos/musicsource_logo_playlists.png $ret .= "\n\n"; return $ret; } else { - my @path = split(",", $param); - my $sid = $path[0] if ( scalar @path > 0); - my $cid = $path[1] if ( scalar @path > 1); + my ($sid,$cid)=$param=~/^(-?\d+),?(.*)$/; $me->{cl} = $hash->{CL} if( ref($hash->{CL}) eq 'HASH' ); $me->{name} = $hash->{NAME}; @@ -330,7 +313,7 @@ sub HEOSPlayer_Get($$@) { my $heosCmd = "browseSource"; my $action; - if ( defined $sid && defined $cid ) { + if ( defined $sid && defined $cid && $cid ne "" ) { if ( $sid eq "1027" ) { $action = "sid=$cid"; @@ -347,6 +330,40 @@ sub HEOSPlayer_Get($$@) { $action = "sid=$sid&cid=$cid"; } + + } elsif ( defined $sid && $sid eq "1029" ) { + + my $ret = "$hash->{NAME}/Warteschlange\n"; + $ret .= sprintf( "%-35s %-15s %s\n", 'key', 'type', 'title' ); + + my $x = 0; + foreach my $item (@{ $hash->{helper}{queue}}) { + + $ret .= HEOSPlayer_MakePlayLink($hash->{NAME}, "1029,".++$x, "heos_queue", $item->{song} ); + } + + $ret .= "\n\n"; + + if( $me->{cl}->{TYPE} eq 'FHEMWEB' ) { + + $ret =~ s/&/&/g; + $ret =~ s/'/'/g; + $ret =~ s/\n/
    /g; + $ret = "
    $ret
    " if( $ret =~ m/ / ); + $ret = "$ret"; + + } else { + + $ret =~ s/]*>//g; + $ret =~ s/<\/a>//g; + $ret =~ s/]*>\n//g; + $ret .= "\n"; + } + + asyncOutput( $me->{cl}, $ret ); + #delete $me; + return undef; + } else { $action = "sid=$sid"; @@ -461,7 +478,7 @@ sub HEOSPlayer_Set($$@) { foreach ( split('\,', $args[0]) ) { - $string .= ",$defs{$_}->{PID}"; + $string .= ",$defs{$_}->{PID}" if ( defined $defs{$_} ); printf "String: $string\n"; } @@ -490,30 +507,52 @@ sub HEOSPlayer_Set($$@) { $heosCmd = 'playPresetStation'; if ( $cmd eq 'channel' ) { - return "usage: channel 1-$favoritcount" if( @args != 1 ); + return "usage: channel 1-$favoritcount" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > $favoritcount || $args[0] < 1); $action = "preset=$args[0]"; } elsif( $cmd eq 'channelUp' ) { return "usage: $cmd" if( @args != 0 ); - $favorit = $favoritcount if ( ++$favorit > $favoritcount ); + ++$favorit; + if ( $favorit > $favoritcount ) { + if ( AttrVal($name, 'channelring', 0) == 1 ) { + + $favorit = 1; + + } else { + + $favorit = $favoritcount; + } + } + $action = "preset=".$favorit; } elsif( $cmd eq 'channelDown' ) { return "usage: $cmd" if( @args != 0 ); - $favorit = 1 if ( --$favorit <= 0 ); + --$favorit; + if ( $favorit <= 0 ) { + if ( AttrVal($name, 'channelring', 0) == 1 ) { + + $favorit = $favoritcount; + + } else { + + $favorit = 1; + } + } + $action = "preset=".$favorit; } } elsif ( $cmd =~ /Queue/ ) { $heosCmd = $cmd; - if ( $cmd eq 'playQueue' ) { + if ( $cmd eq 'playQueueItem' ) { $qcount = scalar(@{$hash->{helper}{queue}}) if ( defined $hash->{helper}{queue} ); - return "usage: queue 1-$qcount" if( @args != 1 ); + return "usage: queue 1-$qcount" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > $qcount || $args[0] < 1); $action = "qid=$args[0]"; @@ -584,90 +623,86 @@ sub HEOSPlayer_Set($$@) { readingsSingleUpdate($hash, "input", $args[0], 1); } elsif( $cmd eq 'input' ) { - return 'usage: '.$cmd.' sid[,cid][,mid]' if( @args != 1 ); + return "usage: $cmd sid[,cid][,mid]" if( @args != 1 ); my $param = shift( @args ); - my @path = split( ",", $param); - my $sid = $path[0] if ( scalar @path > 0); - my $cid = $path[1] if ( scalar @path > 1); - my $mid = $path[2] if ( scalar @path > 2); + my ($sid,$cid,$mid)=$param=~/^(-?\d+),(.+?)(?:,(.*))?/; - if ( $sid =~ /^-*[0-9]+$/ ) { - if ( $sid eq "1024" ) { - return 'usage: '.$cmd.' sid,cid[,mid]' unless( defined($cid) && defined($mid) ); + return "usage: $cmd sid[,cid][,mid]" unless( defined $sid || $sid eq "" ); + + if ( $sid eq "1024" ) { + return "usage: $cmd sid,cid[,mid]" unless( defined($cid) && defined($mid) ); + + #Server abspielen + $heosCmd = 'playPlaylist'; + $action = "sid=$sid&cid=$cid&aid=4"; + $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); + + } elsif ( $sid eq "1025" ) { + return "usage: $cmd sid,cid[,mid]" unless( defined($cid) ); + + #Playlist abspielen + $heosCmd = 'playPlaylist'; + $action = "sid=$sid&cid=$cid&aid=4"; + $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); + + } elsif ( $sid eq "1026" ) { + return "usage: $cmd sid,cid,mid" unless( defined($cid) ); + + #Verlauf abspielen + if ( $cid eq "TRACKS" ) { + + $heosCmd = 'playPlaylist'; + $action = "sid=$sid&cid=$cid&aid=4"; + $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); + + } elsif ( $cid eq "STATIONS" ) { + + $heosCmd = 'playStream'; + $action = "sid=$sid&cid=$cid&mid=$mid"; + } + + } elsif ( $sid eq "1027" ) { + return "usage: $cmd sid,spid,mid" unless( defined($cid) ); + + #Eingang abspielen + $heosCmd = 'playInput'; + $action = "input=$mid"; + $action = "spid=$cid&".$action if ( $pid ne $cid ); + + } elsif ( $sid eq "1028" ) { + return "usage: $cmd sid,nr" unless( defined($cid) ); + + #Favoriten abspielen + $heosCmd = 'playPresetStation'; + $action = "preset=$cid"; + + } elsif ( $sid eq "1029" ) { + return "usage: $cmd sid,qid" unless( defined($cid) ); + + #Warteschlange abspielen + $heosCmd = 'playQueue'; + $action = "qid=$cid"; + + } else { + if ( $sid > 0 && $sid < 1024 ) { + return "usage: $cmd sid,cid,mid" unless( defined($cid) && defined($mid) ); + + #Radio abspielen + $heosCmd = 'playStream'; + $action = "sid=$sid&cid=$cid&mid=$mid"; + + } else { + return "usage: $cmd sid,cid[,mid]" unless( defined($cid) ); #Server abspielen $heosCmd = 'playPlaylist'; $action = "sid=$sid&cid=$cid&aid=4"; $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); - } elsif ( $sid eq "1025" ) { - return 'usage: '.$cmd.' sid,cid[,mid]' unless( defined($cid) ); - - #Playlist abspielen - $heosCmd = 'playPlaylist'; - $action = "sid=$sid&cid=$cid&aid=4"; - $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); - - } elsif ( $sid eq "1026" ) { - return 'usage: '.$cmd.' sid,cid,mid' unless( defined($cid) ); - - #Verlauf abspielen - if ( $cid eq "TRACKS" ) { - - $heosCmd = 'playPlaylist'; - $action = "sid=$sid&cid=$cid&aid=4"; - $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); - - } elsif ( $cid eq "STATIONS" ) { - - $heosCmd = 'playStream'; - $action = "sid=$sid&cid=$cid&mid=$mid"; - } - - } elsif ( $sid eq "1027" ) { - return 'usage: '.$cmd.' sid,spid,mid' unless( defined($cid) ); - - #Eingang abspielen - $heosCmd = 'playInput'; - $action = "input=$mid"; - $action = "spid=$cid&".$action if ( $pid ne $cid ); - - } elsif ( $sid eq "1028" ) { - return 'usage: '.$cmd.' sid,nr' unless( defined($cid) ); - - #Favoriten abspielen - $heosCmd = 'playPresetStation'; - $action = "preset=$cid"; - - } elsif ( $sid eq "1029" ) { - return 'usage: '.$cmd.' sid,qid' unless( defined($cid) ); - - #Warteschlange abspielen - $heosCmd = 'playQueue'; - $action = "qid=$sid"; - - } else { - if ( $sid > 0 && $sid < 30 ) { - return 'usage: '.$cmd.' sid,cid,mid' unless( defined($cid) && defined($mid) ); - - #Radio abspielen - $heosCmd = 'playStream'; - $action = "sid=$sid&cid=$cid&mid=$mid"; - - } else { - return 'usage: '.$cmd.' sid,cid[,mid]' unless( defined($cid) ); - - #Server abspielen - $heosCmd = 'playPlaylist'; - $action = "sid=$sid&cid=$cid&aid=4"; - $action = "sid=$sid&cid=$cid&mid=$mid&aid=4" if ( defined($mid) ); - } } - } else { - - return 'usage: '.$cmd.' sid,cid[,mid]'; } + } else { my $list = "getPlayerInfo:noArg getPlayState:noArg getNowPlayingMedia:noArg getPlayMode:noArg play:noArg stop:noArg pause:noArg mute:on,off volume:slider,0,5,100 volumeUp:slider,0,1,10 volumeDown:slider,0,1,10 repeat:one,all,off shuffle:on,off next:noArg prev:noArg input"; @@ -686,14 +721,14 @@ sub HEOSPlayer_Set($$@) { if ( defined($hash->{helper}{queue}) && ref($hash->{helper}{queue}) eq "ARRAY" && scalar(@{$hash->{helper}{queue}}) > 0 ) { - $list .= " playQueue:slider,1,1,".scalar(@{$hash->{helper}{queue}}) if ( defined $hash->{helper}{queue} ); + $list .= " playQueueItem:slider,1,1,".scalar(@{$hash->{helper}{queue}}) if ( defined $hash->{helper}{queue} ); $list .= " clearQueue:noArg saveQueue"; } if ( defined $hash->{IODev}{helper}{playlists} ) { my @playlists = map { my %n; $n{name} = $_->{name}; $n{name} =~ s/\s+/\ /g; $n{name} } (@{ $hash->{IODev}{helper}{playlists}}); - #$list .= " playPlaylistItem:slider,1,1,".scalar @playlists; + $list .= " playPlaylist:".join(",",@playlists) if( scalar @playlists > 0 ); $list .= " deletePlaylist:".join(",",@playlists) if( scalar @playlists > 0 ); } @@ -772,7 +807,7 @@ sub HEOSPlayer_WriteReadings($$) { my $name = $hash->{NAME}; - Log3 $name, 3, "HEOSPlayer ($name) - processing data to write readings"; + Log3 $name, 4, "HEOSPlayer ($name) - processing data to write readings"; ############################ #### Aufbereiten der Daten soweit nötig (bei Events zum Beispiel) my $readingsHash = HEOSPlayer_PreProcessingReadings($hash,$decode_json) @@ -887,7 +922,7 @@ sub HEOSPlayer_PreProcessingReadings($$) { } else { - Log3 $name, 3, "HEOSPlayer ($name) - no match found"; + Log3 $name, 4, "HEOSPlayer ($name) - no match found"; return undef; } @@ -958,29 +993,42 @@ sub HEOSPlayer_GetQueue($) { IOWrite($hash,'getQueue',"pid=$hash->{PID}",undef); } -sub HEOSPlayer_Hexdump { +sub HEOSPlayer_MakePlayLink($$$$) { - my $str = ref $_[0] ? ${$_[0]} : $_[0]; + my ($name, $sid, $itemtype, $itemname) = @_; + my $xcmd = 'cmd'.uri_escape('=get '.$name.' ls '.$sid); + my $xtext = $sid; - return "[ZERO-LENGTH STRING]\n" unless length $str; + $xcmd = 'cmd'.uri_escape('=set '.$name.' input '.$sid) if ( $itemtype eq "heos_queue" ); + $xcmd = "FW_cmd('$FW_ME$FW_subdir?XHR=1&$xcmd')"; + return '
  • '.sprintf( "%-35s %-15s %s", $xtext, $itemtype, $itemname )."
  • \n"; +} - # split input up into 16-byte chunks: - my @chunks = $str =~ /([\0-\377]{1,16})/g; - # format and print: - my @print; - for (@chunks) { - my $hex = unpack "H*", $_; - tr/ -~/./c; # mask non-print chars - $hex =~ s/(..)(?!$)/$1 /g; # insert spaces in hex - # make sure our hex output has the correct length - $hex .= ' ' x ( length($hex) < 48 ? 48 - length($hex) : 0 ); - push @print, "$hex $_\n"; - } - wantarray ? @print : join '', @print; +sub HEOSPlayer_MakePlayLink2($$$$) { + + my ($name, $sid, $itemname, $itemurl, $xsize, $ysize) = @_; + my $xcmd = 'cmd'.uri_escape('=get '.$name.' ls '.$sid); + my $xtext = $sid; + + $xcmd = "FW_cmd('$FW_ME$FW_subdir?XHR=1&$xcmd')"; + return '
  • '.$itemname."
  • \n"; +} + +sub HEOSPlayer_makeImage($$) { + my ($url, $xsize, $ysize) = @_; + + my $ret .= "\n"; + + return $ret; } + + + + + 1;