From 4f39f2dd5257a834e81df53b84da04cc6e4b8b68 Mon Sep 17 00:00:00 2001 From: Beta-User <> Date: Wed, 11 Jan 2023 19:11:55 +0000 Subject: [PATCH] 73_MPD: Maintainer update; include events from newer mpd versions, #130801 git-svn-id: https://svn.fhem.de/fhem/trunk@27027 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/73_MPD.pm | 152 +++++++++++++++++++++++++++++++++----------- fhem/MAINTAINER.txt | 2 +- 3 files changed, 117 insertions(+), 38 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 6e9973ae2..a8b275d73 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -2,6 +2,7 @@ # Do not insert empty lines here, update check depends on it. - change: 93_DbRep: write TYPE uppercase with writeToDB option, Commandref edited + - bugfix: 73_MPD: adopt to newer mpd versions with more events - bugfix: 59_Weather: fix DarkSky API wrong funtion call - feature: 72_FRITZBOX: merged old 72_FRITZBOX with last Fork Version - bugfix: 59_Weather: bugfix function WeatherAsHtmlD not working diff --git a/fhem/FHEM/73_MPD.pm b/fhem/FHEM/73_MPD.pm index ee199c4b5..ad5995b95 100644 --- a/fhem/FHEM/73_MPD.pm +++ b/fhem/FHEM/73_MPD.pm @@ -48,7 +48,7 @@ use strict; use warnings; use Time::HiRes qw(gettimeofday); use URI::Escape; -use POSIX; +#use POSIX; use Blocking; # http://www.fhemwiki.de/wiki/Blocking_Call use IO::Socket; use Getopt::Std; @@ -161,7 +161,7 @@ sub MPD_updateConfig($) $hash->{helper}{playlistcollection}{val} = -1; $hash->{".password"} = AttrVal($name, "password", ""); - $hash->{TIMEOUT} = AttrVal($name, "timeout", 2); + $hash->{TIMEOUT} = AttrVal($name, 'timeout', 0.7); $hash->{".sMusicL"} = AttrVal($name, "stateMusic", 1); $hash->{".sPlayL"} = AttrVal($name, "statePlaylists", 1); $hash->{".apikey"} = AttrVal($name, "lastfm_api_key", "f3a26c7c8b4c4306bc382557d5c04ad5"); @@ -202,7 +202,7 @@ sub MPD_updateConfig($) readingsEndUpdate($hash,0); MPD_Outputs_Status($hash); - mpd_cmd($hash, clb.cle); + mpd_cmd($hash, clb.cle) if ReadingsVal($name,'presence','none') ne 'absent'; if ($hash->{".volume"} eq "0") { # ist Mute aktiv oder soll sie mit Absicht 0 sein ? @@ -233,7 +233,7 @@ sub MPD_updateConfig($) { # Playlisten und Musik Dir laden ? # nicht bei Player mopidy, listall wird von ihm nicht unterstützt ! - if ((AttrVal($name, "loadMusic", "1") eq "1") && !$error && ($hash->{".player"} ne "mopidy")) + if ((AttrVal($name, 'loadMusic', '0') eq '1') && !$error && ($hash->{'.player'} ne 'mopidy')) # Beta-User: listall is deprecated on the MPD side, see docu at https://mpd.readthedocs.io/en/latest/protocol.html#the-music-database { $error = mpd_cmd($hash, "i|listall|music"); Log3 $name,3,"$name, error loading music -> $error" if ($error); @@ -330,6 +330,7 @@ sub MPD_Attr (@) } elsif (($attrName eq "disable") && ($attrVal == 0)) { + return if !$init_done; $attr{$name}{disable} = $attrVal; readingsSingleUpdate($hash,"state","reset",1); $hash->{".reset"} = 1; @@ -383,7 +384,7 @@ sub MPD_Attr (@) $attr{$name}{disable} = 0; readingsSingleUpdate($hash,"state","reset",1); $hash->{".reset"}=1; - MPD_updateConfig($hash); + MPD_updateConfig($hash); } elsif ($attrName eq "statePlaylists") { $hash->{".sPlayL"} = 1; } elsif ($attrName eq "stateMusic") { $hash->{".sMusicL"} = 1; } @@ -455,8 +456,9 @@ sub MPD_Set($@) my $subcmd = (defined($a[2])) ? $a[2] : ""; return undef if ($subcmd eq '---'); # erster Eintrag im select Feld ignorieren - my $step = int(AttrVal($name, "volumeStep", 5)); # vllt runtersetzen auf default = 2 ? - my $vol_now = int($hash->{".volume"}); + my $step = int(AttrVal($name, 'volumeStep', 5)); # vllt runtersetzen auf default = 2 ? + my $vol_now = $hash->{'.volume'} // 0; + $vol_now = int($vol_now); my $vol_new; if ($cmd eq "reset") { $hash->{".reset"} = 1; MPD_updateConfig($hash); return undef;} @@ -966,6 +968,7 @@ sub MPD_Outputs_Status($) { my ($hash)= @_; my $name = $hash->{NAME}; + return if ReadingsVal($name,'presence','none') eq 'absent'; $hash->{".outputs"} = mpd_cmd($hash, "i|outputs|x"); my @outp = split("\n" , $hash->{".outputs"}); readingsBeginUpdate($hash); @@ -973,6 +976,7 @@ sub MPD_Outputs_Status($) foreach (@outp) { my @val = split(": " , $_); + next if !defined $val[1]; Log3 $name, 4 ,"$name, MPD_Outputs_Status -> $val[0] = $val[1]"; $outpid = ($val[0] eq "outputid") ? $val[1] : $outpid; readingsBulkUpdate($hash,$val[0].$outpid,$val[1]) if ($val[0] ne "outputid"); @@ -1020,8 +1024,24 @@ sub mpd_cmd($$) return $!; } - while (<$sock>) # MPD rede mit mir , egal was ;) - { last if $_ ; } # end of output. +# my $read = new IO::Select() || return 'Error in calling IO::Select!\n'; +# $read->add($sock); +# my @count = $read->can_read($hash->{TIMEOUT}); +# return 'error - no data received from MPD!\n' if @count < 1; + + if ( !eval { + $SIG{ALRM} = sub {Carp::carp 'timeout';}; + alarm(1); + while (<$sock>) # MPD rede mit mir , egal was ;) + { last if $_ ; } # end of output. + alarm(0); + 1; } + ) { + return $@ if $@; + } + +# while (<$sock>) # MPD rede mit mir , egal was ;) +# { last if $_ ; } # end of output. chomp $_; @@ -1207,6 +1227,10 @@ sub MPD_IdleStart($) return $name."|IdleStart: $!" if (!$sock); + my $read = new IO::Select() || return 'Fehler beim Aufruf von IO::Select!\n'; + $read->add($sock); + my @count = $read->can_read($hash->{TIMEOUT}); + return "Fehler - keine Daten vom MPD!\n" if @count < 1; while (<$sock>) { last if $_ ; } chomp $_; @@ -1248,7 +1272,7 @@ sub MPD_IdleStart($) $_ =~s/changed: //g; - if (($_ ne $old_event) && ($_ ne "OK") && (index($_,": ") == -1)) + if (($_ ne $old_event) && ($_ ne "OK") && (index($_,": ") == -1) ) { $output .= ($old_event eq "") ? $_ : "+".$_; $old_event = $_; @@ -1257,7 +1281,16 @@ sub MPD_IdleStart($) elsif (index($_,": ") > -1){ $output .= "|".$_; $step=1; - } + } + elsif ($_ !~ m{\Aplayer|playlist|mixer|options|update\z}x){ + print $sock "idle\n"; + $step=1; + readingsSingleUpdate($hash,'last_error',$_,1); + } + elsif ($_ eq 'update'){ #might be extended for other new message types w/o further action to FHEM + print $sock "idle\n"; + $step=1; + } else #if ($_ eq "OK") { print $sock "idle\n" if($step) ; @@ -2225,13 +2258,17 @@ sub MPD_SaveBookmark($) 1; +__END__ + =pod + +=encoding utf8 =item device =item summary controls MPD or Mopidy music server =item summary_DE steuert den MPD oder Mopidy Musik Server =begin html - +
set <name> <what>
get <name> <what>
define rg_artist readingsGroup <MPD name>:artist,artist_image_html,artist_summary attr rg_artist room MPD
set <name> <was>
get <name> <was>
define rg_artist readingsGroup <MPD name>:artist,artist_image_html,artist_summary attr rg_artist room MPD