From 4bd8f000f80d6383c0e0c8d2dd42de287e6668b3 Mon Sep 17 00:00:00 2001 From: Reinerlein <> Date: Sun, 7 Jan 2018 22:42:45 +0000 Subject: [PATCH] SONOS: Change SubProcess-checking routine. Change logging. git-svn-id: https://svn.fhem.de/fhem/trunk@15823 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_SONOS.pm | 28 ++++++------- fhem/FHEM/21_SONOSPLAYER.pm | 2 +- fhem/FHEM/lib/UPnP/ControlPoint.pm | 63 ++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/fhem/FHEM/00_SONOS.pm b/fhem/FHEM/00_SONOS.pm index 496513c4b..1d1a84874 100755 --- a/fhem/FHEM/00_SONOS.pm +++ b/fhem/FHEM/00_SONOS.pm @@ -1,6 +1,6 @@ ######################################################################################## # -# SONOS.pm (c) by Reiner Leins, December 2017 +# SONOS.pm (c) by Reiner Leins, January 2018 # rleins at lmsoft dot de # # $Id$ @@ -51,6 +51,10 @@ # Changelog (last 4 entries only, see Wiki for complete changelog) # # SVN-History: +# 07.01.2018 +# Der Initialwert von LastProcessAnswer (wird beim Start auf 0 gesetzt) wird nun korrekt berücksichtigt +# Bei ignoredIPs und bei usedOnlyIPs kann jetzt für jedes Komma-Getrennte Element auch ein regulärer Ausdruck stehen. Wird mit // umschlossen, und darf keine Doppelpunkte enthalten. +# Logausgabe im UPnP-Modul, welche Devices mit welchen Header-Angaben nun akzeptiert wurden (Ausgabe auf Level 5) # 23.12.2017 # Subscriptions-Refresh umgebaut. # Devicenamen mit Punkt (.) funktionieren nun. @@ -66,8 +70,6 @@ # 14.07.2017 # Änderung in der ControlPoint.pm: Es wurden zuviele Suchantworten berücksichtigt. # Bei einem Modify wird von Fhem nur die DefFn aufgerufen (und nicht vorher UndefFn). Dadurch blieben Reste, die aber vor einer Definition aufgeräumt werden müssen. Resultat war eine 100%-CPU-Last. -# 09.07.2017 -# BulkUpdate: Beginn und Ende sind nun sicher davor einen vom SubProzess gestarteten BulkUpdate vorzeitig zu beenden. # ######################################################################################## # @@ -133,8 +135,8 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # IP-Adressen, die vom UPnP-Modul ignoriert werden sollen. # Diese können über ein Attribut gesetzt werden. ######################################################## -my %ignoredIPs = (); -my %usedonlyIPs = (); +my @ignoredIPs = (); +my @usedonlyIPs = (); my $reusePort = 0; @@ -1943,7 +1945,7 @@ sub SONOS_IsSubprocessAliveChecker() { SONOS_DoWork('undef', 'refreshProcessAnswer') if ($lastProcessAnswer < time() - $hash->{INTERVAL}); # Wenn die letzte Antwort zu lange her ist, dann den SubProzess neustarten... - if ($lastProcessAnswer < time() - (4 * $hash->{INTERVAL})) { + if (($lastProcessAnswer != 0) && ($lastProcessAnswer < time() - (4 * $hash->{INTERVAL}))) { # Verbindung beenden, damit der SubProzess die Chance hat neu initialisiert zu werden... SONOS_Log $hash->{UDN}, 2, 'LastProcessAnswer way too old (Lastanswer: '.$lastProcessAnswer.' ~ '.SONOS_GetTimeString($lastProcessAnswer).')... try to restart the process and connection...'; @@ -2390,7 +2392,7 @@ sub SONOS_Discover() { $SONOS_RestartControlPoint = 0; eval { - $SONOS_Controlpoint = UPnP::ControlPoint->new(SearchPort => 0, SubscriptionPort => 0, SubscriptionURL => '/fhemmodule', MaxWait => 30, UsedOnlyIP => \%usedonlyIPs, IgnoreIP => \%ignoredIPs, ReusePort => $reusePort); + $SONOS_Controlpoint = UPnP::ControlPoint->new(SearchPort => 0, SubscriptionPort => 0, SubscriptionURL => '/fhemmodule', MaxWait => 30, LogLevel => $SONOS_Client_LogLevel, UsedOnlyIP => \@usedonlyIPs, IgnoreIP => \@ignoredIPs, ReusePort => $reusePort); $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback); #$SONOS_Controlpoint->handle; @@ -5001,7 +5003,7 @@ sub SONOS_RestoreOldPlaystate() { SONOS_Log undef, 1, 'Restore-Thread gestartet. Warte auf Arbeit...'; my $runEndlessLoop = 1; - my $controlPoint = UPnP::ControlPoint->new(SearchPort => 0, SubscriptionPort => 0, SubscriptionURL => '/fhemmodule', MaxWait => 20, UsedOnlyIP => \%usedonlyIPs, IgnoreIP => \%ignoredIPs, ReusePort => $reusePort); + my $controlPoint = UPnP::ControlPoint->new(SearchPort => 0, SubscriptionPort => 0, SubscriptionURL => '/fhemmodule', MaxWait => 20, LogLevel => $SONOS_Client_LogLevel, UsedOnlyIP => \@usedonlyIPs, IgnoreIP => \@ignoredIPs, ReusePort => $reusePort); $SIG{'PIPE'} = 'IGNORE'; $SIG{'CHLD'} = 'IGNORE'; @@ -10067,17 +10069,11 @@ sub SONOS_Client_ConsumeMessage($$) { $SONOS_Client_LogfileName = $3; $SONOS_Client_Data{pingType} = $4; - my @usedonlyIPs = split(/,/, $5); + @usedonlyIPs = split(/,/, $5); $SONOS_Client_Data{usedonlyIPs} = shared_clone(\@usedonlyIPs); - for my $elem (@usedonlyIPs) { - $usedonlyIPs{SONOS_Trim($elem)} = 1; - } - my @ignoredIPs = split(/,/, $6); + @ignoredIPs = split(/,/, $6); $SONOS_Client_Data{ignoredIPs} = shared_clone(\@ignoredIPs); - for my $elem (@ignoredIPs) { - $ignoredIPs{SONOS_Trim($elem)} = 1; - } $reusePort = $7; diff --git a/fhem/FHEM/21_SONOSPLAYER.pm b/fhem/FHEM/21_SONOSPLAYER.pm index ef2d726a2..f7a3f2ad6 100755 --- a/fhem/FHEM/21_SONOSPLAYER.pm +++ b/fhem/FHEM/21_SONOSPLAYER.pm @@ -1,6 +1,6 @@ ######################################################################################## # -# SONOSPLAYER.pm (c) by Reiner Leins, December 2017 +# SONOSPLAYER.pm (c) by Reiner Leins, January 2018 # rleins at lmsoft dot de # # $Id$ diff --git a/fhem/FHEM/lib/UPnP/ControlPoint.pm b/fhem/FHEM/lib/UPnP/ControlPoint.pm index 991fcfa45..88a5271d4 100644 --- a/fhem/FHEM/lib/UPnP/ControlPoint.pm +++ b/fhem/FHEM/lib/UPnP/ControlPoint.pm @@ -48,8 +48,47 @@ use constant DEFAULT_SSDP_SEARCH_PORT => 8008; use constant DEFAULT_SUBSCRIPTION_PORT => 8058; use constant DEFAULT_SUBSCRIPTION_URL => '/eventSub'; -our %IGNOREIP; -our %USEDONLYIP; +our @IGNOREIP; +our @USEDONLYIP; +our $LogLevel; + +sub isIgnoreIP($) { + my($ip) = @_; + + foreach my $elem (@IGNOREIP) { + if ($elem =~ m/^\/(.*)\/$/) { + if ($ip =~ m/^$1$/) { + return 1; + } + } else { + if ($ip eq $elem) { + return 1; + } + } + } + + return 0; +} + +sub isUsedOnlyIP($) { + my($ip) = @_; + + return 1 if (!scalar(@USEDONLYIP)); + + foreach my $elem (@USEDONLYIP) { + if ($elem =~ m/^\/(.*)\/$/) { + if ($ip =~ m/^$1$/) { + return 1; + } + } else { + if ($ip eq $elem) { + return 1; + } + } + } + + return 0; +} sub new { my($self, %args) = @_; @@ -60,8 +99,9 @@ sub new { my $searchPort = defined($args{SearchPort}) ? $args{SearchPort} : DEFAULT_SSDP_SEARCH_PORT; my $subscriptionPort = defined($args{SubscriptionPort}) ? $args{SubscriptionPort} : DEFAULT_SUBSCRIPTION_PORT; my $maxWait = $args{MaxWait} || 3; - %IGNOREIP = %{$args{IgnoreIP}}; - %USEDONLYIP = %{$args{UsedOnlyIP}}; + @IGNOREIP = @{$args{IgnoreIP}}; + @USEDONLYIP = @{$args{UsedOnlyIP}}; + $LogLevel = $args{LogLevel} || 0; my $reuseport = $args{ReusePort}; $reuseport = 0 if (!defined($reuseport)); @@ -187,8 +227,8 @@ sub handleOnce { } elsif ($socket == $self->{_subscriptionSocket}) { if (my $connect = $socket->accept()) { - return if (scalar(%USEDONLYIP) && (!$USEDONLYIP{$connect->peerhost()})); - return if ($IGNOREIP{$connect->peerhost()}); + return if (!isUsedOnlyIP($connect->peerhost())); + return if (isIgnoreIP($connect->peerhost())); $self->_receiveSubscriptionNotification($connect); } } @@ -391,8 +431,8 @@ sub _receiveSearchResponse { my $peer = recv($socket, $buf, 2048, 0); my @peerdata = unpack_sockaddr_in($peer); - return if (scalar(%USEDONLYIP) && (!$USEDONLYIP{inet_ntoa($peerdata[1])})); - return if ($IGNOREIP{inet_ntoa($peerdata[1])}); + return if (!isUsedOnlyIP(inet_ntoa($peerdata[1]))); + return if (isIgnoreIP(inet_ntoa($peerdata[1]))); if ($buf !~ /\015?\012\015?\012/) { return; @@ -409,6 +449,7 @@ sub _receiveSearchResponse { foreach my $searchkey (keys %{$self->{_activeSearches}}) { my $search = $self->{_activeSearches}->{$searchkey}; if ($search->{_type} && $buf =~ $search->{_type}) { + print 'xxxx.xx.xx xx:xx:xx 5: ControlPoint: Accepted Search-Response: "'.$buf.'"'."\n" if ($LogLevel >= 5); $found = 1; last; } @@ -426,7 +467,7 @@ sub _receiveSearchResponse { } if (! $found) { - #print "Unknown response: " . Dumper($buf); #ALW uncomment + print 'xxxx.xx.xx xx:xx:xx 5: ControlPoint: Unknown Search-Response: "'.$buf.'"'."\n" if ($LogLevel >= 5); return; } @@ -454,8 +495,8 @@ sub _receiveSSDPEvent { my @peerdata = unpack_sockaddr_in($peer); return if (!@peerdata); - return if (scalar(%USEDONLYIP) && (!$USEDONLYIP{inet_ntoa($peerdata[1])})); - return if ($IGNOREIP{inet_ntoa($peerdata[1])}); + return if (!isUsedOnlyIP(inet_ntoa($peerdata[1]))); + return if (isIgnoreIP(inet_ntoa($peerdata[1]))); if ($buf !~ /\015?\012\015?\012/) { return;