diff --git a/fhem/FHEM/00_SONOS.pm b/fhem/FHEM/00_SONOS.pm
index 5344ce928..496513c4b 100755
--- a/fhem/FHEM/00_SONOS.pm
+++ b/fhem/FHEM/00_SONOS.pm
@@ -1,6 +1,6 @@
########################################################################################
#
-# SONOS.pm (c) by Reiner Leins, July 2017
+# SONOS.pm (c) by Reiner Leins, December 2017
# rleins at lmsoft dot de
#
# $Id$
@@ -51,6 +51,14 @@
# Changelog (last 4 entries only, see Wiki for complete changelog)
#
# SVN-History:
+# 23.12.2017
+# Subscriptions-Refresh umgebaut.
+# Devicenamen mit Punkt (.) funktionieren nun.
+# Fehler mit "undefined value $value" behoben.
+# GetTrackProvider liefert bei Nichtfinden in der MusicServicesList nun eine leere Angabe, und keine undefined.
+# Die Angabe in LastProcessAnswer ist nicht Zeitumstellungsfest. Der Wert wurde nun umgestellt auf epoch-Zeit.
+# Der Verweis auf %intAt wurde entfernt. Die Variable wurde sowieso nie verwendet.
+# Warnungsunterdrückung von 'mumpitzstuff' eingebaut.
# 28.09.2017
# Provider-Icons werden wieder korrekt ermittelt
# Das Verarbeiten der Arbeitsschlange im SubProcess wurde optimiert
@@ -60,8 +68,6 @@
# 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.
-# 05.07.2017
-# Neue Variante für das Ermitteln der laufenden Favoriten, Radios oder Playlists.
#
########################################################################################
#
@@ -135,7 +141,7 @@ my $reusePort = 0;
########################################################
# Standards aus FHEM einbinden
########################################################
-use vars qw{%attr %modules %defs %intAt %data};
+use vars qw{%attr %modules %defs %data};
########################################################
@@ -429,6 +435,9 @@ sub SONOS_getCoverTitleRG($;$$) {
my ($device, $width, $space) = @_;
$width = 500 if (!defined($width));
+ my $saveDevice = $device;
+ $saveDevice =~ s/[^a-zA-Z0-9]//g;
+
my $transportState = ReadingsVal($device, 'transportState', '');
my $presence = ReadingsVal($device, 'presence', 'disappeared');
$presence = 'disappeared' if ($presence =~ m/~~NotLoadedMarker~~/i);
@@ -454,44 +463,44 @@ sub SONOS_getCoverTitleRG($;$$) {
$transportState = FW_makeImage('audio_pause', 'Paused', 'SONOS_Transportstate') if ($transportState eq 'PAUSED_PLAYBACK');
$transportState = FW_makeImage('audio_stop', 'Stopped', 'SONOS_Transportstate') if ($transportState eq 'STOPPED');
- my $fullscreenDiv = '
'.ReadingsVal($device, 'roomName', $device).$transportState.'
'.((lc($presence) eq 'disappeared') ? 'Player disappeared' : ReadingsVal($device, 'infoSummarize1', '')).'
'.md5_hex(ReadingsVal($device, 'roomName', $device).ReadingsVal($device, 'infoSummarize2', '').ReadingsVal($device, 'currentTrackPosition', '').ReadingsVal($device, 'currentAlbumArtURL', '')).'
'.(($normalAudio) ? '
'.$currentRuntime.'
'.$currentStarttime.'
'.$playing.'
' : '').'
';
+ my $fullscreenDiv = ''.ReadingsVal($device, 'roomName', $device).$transportState.'
'.((lc($presence) eq 'disappeared') ? 'Player disappeared' : ReadingsVal($device, 'infoSummarize1', '')).'
'.md5_hex(ReadingsVal($device, 'roomName', $device).ReadingsVal($device, 'infoSummarize2', '').ReadingsVal($device, 'currentTrackPosition', '').ReadingsVal($device, 'currentAlbumArtURL', '')).'
'.(($normalAudio) ? '
'.$currentRuntime.'
'.$currentStarttime.'
'.$playing.'
' : '').'
';
- my $javascriptTimer = 'function refreshTime'.$device.'() {
- var playing = document.getElementById("prog_playing_'.$device.'");
+ my $javascriptTimer = 'function refreshTime'.$saveDevice.'() {
+ var playing = document.getElementById("prog_playing_'.$saveDevice.'");
if (!playing || (playing && (playing.innerHTML == "0"))) {
return;
}
- var runtime = document.getElementById("prog_runtime_'.$device.'");
- var starttime = document.getElementById("prog_starttime_'.$device.'");
+ var runtime = document.getElementById("prog_runtime_'.$saveDevice.'");
+ var starttime = document.getElementById("prog_starttime_'.$saveDevice.'");
if (runtime && starttime) {
var now = new Date().getTime();
var percent = (Math.round(now / 10.0) - Math.round(starttime.innerHTML * 100.0)) / runtime.innerHTML;
- document.getElementById("progressbar'.$device.'").style.width = percent + "%";
+ document.getElementById("progressbar'.$saveDevice.'").style.width = percent + "%";
- setTimeout(refreshTime'.$device.', 100);
+ setTimeout(refreshTime'.$saveDevice.', 100);
}
}';
my $javascriptText = '';
$javascriptText =~ s/\n/ /g;
- return $javascriptText.''.SONOS_getCoverRG($device).' '.SONOS_URI_Escape($fullscreenDiv).' | '.SONOS_getTitleRG($device, $space).' |
';
+ return $javascriptText.''.SONOS_getCoverRG($device).' '.SONOS_URI_Escape($fullscreenDiv).' | '.SONOS_getTitleRG($device, $space).' |
';
}
########################################################################################
@@ -527,7 +536,7 @@ sub SONOS_getCoverRG($;$) {
my $presence = ReadingsVal($device, 'presence', 'disappeared');
$presence = 'disappeared' if ($presence =~ m/~~NotLoadedMarker~~/i);
- return '';
+ return '';
}
########################################################################################
@@ -1708,7 +1717,7 @@ sub SONOS_Read($) {
}
# LastAnswer aktualisieren...
- SONOS_readingsSingleUpdate(SONOS_getSonosPlayerByName(), 'LastProcessAnswer', SONOS_TimeNow(), 1);
+ SONOS_readingsSingleUpdate(SONOS_getSonosPlayerByName(), 'LastProcessAnswer', time(), 1);
# Checker aktivieren...
InternalTimer(gettimeofday() + $hash->{INTERVAL}, 'SONOS_IsSubprocessAliveChecker', $hash, 0);
@@ -1912,7 +1921,7 @@ sub SONOS_InitClientProcess($) {
DevIo_SimpleWrite($hash, "StartThread\n", 2);
# Interner Timer für die Überprüfung der Verbindung zum Client (nicht verwechseln mit dem IsAlive-Timer, der die Existenz eines Sonosplayers überprüft)
- SONOS_readingsSingleUpdate($hash, 'LastProcessAnswer', '2100-01-01 00:00:00', 0);
+ SONOS_readingsSingleUpdate($hash, 'LastProcessAnswer', '0', 0);
InternalTimer(gettimeofday() + ($hash->{INTERVAL} * 2), 'SONOS_IsSubprocessAliveChecker', $hash, 0);
return undef;
@@ -1928,15 +1937,15 @@ sub SONOS_IsSubprocessAliveChecker() {
return undef if (AttrVal($hash->{NAME}, 'disable', 0));
- my $lastProcessAnswer = SONOS_GetTimeFromString(ReadingsVal(SONOS_getSonosPlayerByName()->{NAME}, 'LastProcessAnswer', '2100-01-01 00:00:00'));
+ my $lastProcessAnswer = ReadingsVal(SONOS_getSonosPlayerByName()->{NAME}, 'LastProcessAnswer', '0');
# Wenn länger nichts passiert ist, dann eine Aktualisierung anfordern...
- SONOS_DoWork('undef', 'refreshProcessAnswer') if ($lastProcessAnswer < gettimeofday() - $hash->{INTERVAL});
+ SONOS_DoWork('undef', 'refreshProcessAnswer') if ($lastProcessAnswer < time() - $hash->{INTERVAL});
# Wenn die letzte Antwort zu lange her ist, dann den SubProzess neustarten...
- if ($lastProcessAnswer < gettimeofday() - (4 * $hash->{INTERVAL})) {
+ if ($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: '.SONOS_GetTimeString($lastProcessAnswer).')... try to restart the process and connection...';
+ SONOS_Log $hash->{UDN}, 2, 'LastProcessAnswer way too old (Lastanswer: '.$lastProcessAnswer.' ~ '.SONOS_GetTimeString($lastProcessAnswer).')... try to restart the process and connection...';
# Letzten Zeitpunkt und Anzahl der Neustarts merken...
my $sHash = SONOS_getSonosPlayerByName();
@@ -1956,42 +1965,6 @@ sub SONOS_IsSubprocessAliveChecker() {
RemoveInternalTimer($hash, 'SONOS_IsSubprocessAliveChecker');
InternalTimer(gettimeofday() + $hash->{INTERVAL}, 'SONOS_IsSubprocessAliveChecker', $hash, 0);
}
-
- #my $answer;
- ## Neue Verbindung parallel zur bestehenden Kommunikationsleitung.
- ## Nur zum Prüfen, ob der SubProzess noch lebt und antworten kann.
- #my $socket = new IO::Socket::INET(PeerAddr => $hash->{DeviceName}, Proto => 'tcp');
- #if ($socket) {
- # $socket->sockopt(SO_LINGER, pack("ii", 1, 0));
- #
- # $socket->recv($answer, 500);
- # $socket->send("Test\r\n", 0);
- #
- # $socket->shutdown(2);
- # $socket->close();
- #}
- ## Ab hier keine Parallelverbindung mehr offen...
- #
- #if (defined($answer)) {
- # $answer =~ s/[\r\n]//g;
- #}
- #
- #if (!defined($answer) || ($answer !~ m/^This is UPnP-Server listening for commands/)) {
- # SONOS_Log undef, 0, 'No (or incorrect) answer from Subprocess. Restart Sonos-Subprocess...';
- #
- # # Verbindung beenden, damit der SubProzess die Chance hat neu initialisiert zu werden...
- # RemoveInternalTimer($hash);
- # DevIo_SimpleWrite($hash, "disconnect\n", 2);
- # DevIo_CloseDev($hash);
- #
- # # Neu anstarten...
- # SONOS_StartClientProcessIfNeccessary($hash->{DeviceName}) if ($SONOS_StartedOwnUPnPServer);
- # InternalTimer(gettimeofday() + $hash->{WAITTIME}, 'SONOS_DelayOpenDev', $hash, 0);
- #} elsif (defined($answer) && ($answer =~ m/^This is UPnP-Server listening for commands/)) {
- # SONOS_Log undef, 4, 'Got correct answer from Subprocess...';
- # RemoveInternalTimer($hash, 'SONOS_IsSubprocessAliveChecker');
- # InternalTimer(gettimeofday() + $hash->{INTERVAL}, 'SONOS_IsSubprocessAliveChecker', $hash, 0);
- #}
}
########################################################################################
@@ -2285,18 +2258,6 @@ sub SONOS_Set($@) {
}
}
}
-
- # Jetzt noch die Mengen sicherstellen
- # Dazu aktuellen Zustand nochmal holen
- #@current = ();
- #$current = SONOS_Get($hash, qw($hash->{NAME} Groups));
- #$current =~ s/ //g;
- #while ($current =~ m/(\[.*?\])/ig) {
- # my @tmp = split(/,/, substr($1, 1, -1));
- # push @current, \@tmp;
- #}
- #SONOS_Log undef, 5, "Current after List: ".Dumper(\@current);
-
} elsif (lc($key) =~ m/^(Stop|Pause|Mute|MuteOn|MuteOff)(All|)$/i) {
my $commandType = lc($1);
my $commandValue = $value;
@@ -4043,222 +4004,15 @@ sub SONOS_Discover_DoQueue($) {
SONOS_MakeSigHandlerReturnValue($udn, 'LastActionResult', ucfirst($workType).': '.SONOS_AnswerMessage(1));
} elsif ($workType eq 'renewSubscription') {
- if (defined($SONOS_TransportSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_TransportSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_TransportSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'Transport-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! Transport-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_RenderingSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_RenderingSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_RenderingSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'Rendering-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! Rendering-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_GroupRenderingSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_GroupRenderingSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_GroupRenderingSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'GroupRendering-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! GroupRendering-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_ContentDirectorySubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_ContentDirectorySubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_ContentDirectorySubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'ContentDirectory-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! ContentDirectory-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_AlarmSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_AlarmSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_AlarmSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'Alarm-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! Alarm-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_ZoneGroupTopologySubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_ZoneGroupTopologySubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_ZoneGroupTopologySubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'ZoneGroupTopology-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! ZoneGroupTopology-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_DevicePropertiesSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_DevicePropertiesSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_DevicePropertiesSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'DeviceProperties-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! DeviceProperties-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_AudioInSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_AudioInSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_AudioInSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'AudioIn-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! AudioIn-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
- if (defined($SONOS_MusicServicesSubscriptions{$udn}) && (Time::HiRes::time() - $SONOS_MusicServicesSubscriptions{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
- eval {
- $SONOS_MusicServicesSubscriptions{$udn}->renew();
- SONOS_Log $udn, 3, 'MusicServices-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
- };
- if ($@) {
- SONOS_Log $udn, 3, 'Error! MusicServices-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
-
- # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
- # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
- if ($@ =~ m/Can.t connect to/) {
- SONOS_DeleteProxyObjects($udn);
-
- # Player-Informationen aktualisieren...
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
- SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
-
- # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
- $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
- }
- }
- }
-
+ SONOS_ProcessRenew($udn, 'Transport', \%SONOS_TransportSubscriptions);
+ SONOS_ProcessRenew($udn, 'Rendering', \%SONOS_RenderingSubscriptions);
+ SONOS_ProcessRenew($udn, 'GroupRendering', \%SONOS_GroupRenderingSubscriptions);
+ SONOS_ProcessRenew($udn, 'ContentDirectory', \%SONOS_ContentDirectorySubscriptions);
+ SONOS_ProcessRenew($udn, 'Alarm', \%SONOS_AlarmSubscriptions);
+ SONOS_ProcessRenew($udn, 'ZoneGroupTopology', \%SONOS_ZoneGroupTopologySubscriptions);
+ SONOS_ProcessRenew($udn, 'DeviceProperties', \%SONOS_DevicePropertiesSubscriptions);
+ SONOS_ProcessRenew($udn, 'AudioIn', \%SONOS_AudioInSubscriptions);
+ SONOS_ProcessRenew($udn, 'MusicServices', \%SONOS_MusicServicesSubscriptions);
} elsif ($workType eq 'startHandle') {
if ($params[0] =~ m/^(.+)\|(.+)$/) {
my $songURI = $1;
@@ -4417,6 +4171,41 @@ sub SONOS_Discover_DoQueue($) {
}
}
+########################################################################################
+#
+# SONOS_ProcessRenew - Process the renewal of sbscriptions
+#
+########################################################################################
+sub SONOS_ProcessRenew($$$) {
+ my ($udn, $subscriptionName, $subscriptionHash) = @_;
+
+ if (defined($subscriptionHash->{$udn}) && (Time::HiRes::time() - $subscriptionHash->{$udn}->{_startTime} > $SONOS_SUBSCRIPTIONSRENEWAL)) {
+ eval {
+ $SIG{__WARN__} = sub { $_ = shift; };
+
+ $subscriptionHash->{$udn}->renew();
+ SONOS_Log $udn, 3, $subscriptionName.'-Subscription for ZonePlayer "'.$udn.'" has expired and is now renewed.';
+ };
+ if ($@) {
+ SONOS_Log $udn, 3, 'Error! '.$subscriptionName.'-Subscription for ZonePlayer "'.$udn.'" has expired and could not be renewed: '.$@;
+
+ # Wenn der Player nicht erreichbar war, dann entsprechend entfernen...
+ # Hier aber nur eine kleine Lösung, da es nur ein Notbehelf sein soll...
+ if ($@ =~ m/Can.t connect to/i) {
+ SONOS_DeleteProxyObjects($udn);
+
+ # Player-Informationen aktualisieren...
+ SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
+ SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
+ SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
+
+ # Discovery neu anstarten, falls der Player irgendwie doch noch erreichbar sein sollte...
+ $SONOS_Search = $SONOS_Controlpoint->searchByType('urn:schemas-upnp-org:device:ZonePlayer:1', \&SONOS_Discover_Callback);
+ }
+ }
+ }
+}
+
########################################################################################
#
# SONOS_GetBrowseStructuredResult - Browse and give the result back
@@ -5467,6 +5256,8 @@ sub SONOS_GetTrackProvider($;$) {
return ($result, $roundIcon, $quadraticIcon);
}
}
+
+ return ('', '', '');
};
if ($@) {
SONOS_Log undef, 2, 'Unable to identify TrackProvider for "'.$songURI.'". Revert to empty default! Errormessage: '.$@;
@@ -6623,8 +6414,6 @@ sub SONOS_IsAlive($) {
$result = 0;
SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'presence', 'disappeared');
- # Brauchen wir das wirklich? Dabei werden die lokalen Infos nicht aktualisiert...
- #SONOS_Client_Notifier('deleteCurrentNextTitleInformationAndDisappear:'.$udn);
SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'state', 'disappeared');
SONOS_Client_Data_Refresh('ReadingsSingleUpdateIfChanged', $udn, 'transportState', 'STOPPED');
$doDeleteProxyObjects = 1;
@@ -10211,11 +10000,11 @@ sub SONOS_Client_Data_Refresh($$$$) {
my $udnBuffer = ($udn eq 'undef') ? 'SONOS' : $udn;
- SONOS_Log undef, 4, "SONOS_Client_Data_Refresh(".(defined($sendCommand) ? $sendCommand : 'undef').", $udn, $name, $value)";
+ SONOS_Log undef, 4, 'SONOS_Client_Data_Refresh('.(defined($sendCommand) ? $sendCommand : 'undef').", $udn, $name, ".(defined($value) ? $value : 'undef').')';
$SONOS_Client_Data{Buffer}->{$udnBuffer}->{$name} = $value;
if (defined($sendCommand) && ($sendCommand ne '')) {
- SONOS_Client_Notifier($sendCommand.':'.$udn.':'.$name.':'.$value);
+ SONOS_Client_Notifier($sendCommand.':'.$udn.':'.$name.':'.(defined($value) ? $value : 'undef'));
}
}
diff --git a/fhem/FHEM/21_SONOSPLAYER.pm b/fhem/FHEM/21_SONOSPLAYER.pm
index f8a429ba3..ef2d726a2 100755
--- a/fhem/FHEM/21_SONOSPLAYER.pm
+++ b/fhem/FHEM/21_SONOSPLAYER.pm
@@ -1,6 +1,6 @@
########################################################################################
#
-# SONOSPLAYER.pm (c) by Reiner Leins, July 2017
+# SONOSPLAYER.pm (c) by Reiner Leins, December 2017
# rleins at lmsoft dot de
#
# $Id$
@@ -258,7 +258,7 @@ sub SONOSPLAYER_Detail($$$;$) {
return '' if (!ReadingsVal($d, 'IsMaster', 0) || (ReadingsVal($d, 'playerType', '') eq 'ZB100'));
# Open incl. Inform-Div
- my $html .= '';
+ my $html .= '
';
# Cover-/TitleView
$html .= '
';