diff --git a/fhem/CHANGED b/fhem/CHANGED index df1b7d9ac..21b53b64f 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 76_SMAPortal: new attribute cookieDelete - feature: 32_withings: added ecg reading types for scanwatch - change: 59_Twilight: get weather-dependend data by NotifyFn. Existent DEF may be changed automatically! diff --git a/fhem/FHEM/76_SMAPortal.pm b/fhem/FHEM/76_SMAPortal.pm index 19adce382..7e3ab9ae1 100644 --- a/fhem/FHEM/76_SMAPortal.pm +++ b/fhem/FHEM/76_SMAPortal.pm @@ -137,6 +137,8 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "3.5.0" => "10.10.2020 _getLiveData: get data from Dashboard instead of homemanager site depending of attr noHomeManager, ". + "extract OperationHealth key, new attr cookieDelete ", "3.4.1" => "18.08.2020 add selected providerlevel to deletion blacklist # Forum: https://forum.fhem.de/index.php/topic,102112.msg1078990.html#msg1078990 ", "3.4.0" => "09.08.2020 attr balanceDay, balanceMonth, balanceYear for data provider balanceDayData, balanceMonthData, balanceYearData ". "set getData command, update button in header of PortalAsHtml, minor code changes according PBP", @@ -213,8 +215,8 @@ my %vNotesIntern = ( # Voreinstellungen my $maxretries = 6; # max. Anzahl Wiederholungen in einem Abruf-Zyklus my $thold = int($maxretries/2); # Schwellenwert nicht erfolgreicher Leseversuche in einem Zyklus mit dem gleichen Cookie, Standard: int($maxretries/2) -my $sleepretry = 60; # Sleep zwischen Data Call Retries (ohne Threshold Überschreitung) -my $sleepexc = 90; # Sleep vor neuem Datencall nach Überschreitung Threshold (neues Cookie wird angelegt) +my $sleepretry = 60; # Sleep zwischen Data Call Retries +my $sleepexc = 90; # Sleep vor neuem Cycle my $defmaxcycles = 10; # Standard max. Anzahl Datenabrufzyklen my %statkeys = ( # Statistikdaten auszulesende Schlüssel @@ -300,6 +302,7 @@ sub Initialize { "balanceMonth ". "balanceYear ". "cookieLocation ". + "cookieDelete:auto,afterRun,afterCycle,afterAttempt,afterAttempt&Run ". "disable:0,1 ". "interval ". "noHomeManager:1,0 ". @@ -746,9 +749,8 @@ return; # Hauptschleife BlockingCall # $hash->{HELPER}{GETTER} -> Flag für get Informationen # $hash->{HELPER}{SETTER} -> Parameter für set-Befehl -# $nc = 1 wenn Cycle Zähler nicht zurückgesetzt werden soll -# $nr = 1 wenn Retry Zähler nicht zurückgesetzt werden soll -# +# $nc = 1 weiterer Cycle (Cycle Zähler nicht zurücksetzten) +# $nr = 1 weiterer Retry (Zähler nicht zurücksetzten) ################################################################ sub CallInfo { ## no critic 'complexity' my ($hash,$nc,$nr) = @_; @@ -820,11 +822,19 @@ sub CallInfo { ## no critic 'complexity' } } - if(!$nc) { + if(!$nc) { # kein weiterer Cycle, d.h. erster Cycle $hash->{HELPER}{ACTCYCLE} = 1; $hash->{HELPER}{CYCLEBTIME} = (gettimeofday())[0]; } - $hash->{HELPER}{RETRIES} = 1 if(!$nr); + else { # es ist ein weiterer Cycle + if(AttrVal($name, "cookieDelete", "auto") eq "afterCycle") { + delcookiefile ($hash); + } + } + + if(!$nr) { # es ist keine weiterer Attempt, d.h. erster Attempt + $hash->{HELPER}{RETRIES} = 1; + } my $ac = $hash->{HELPER}{ACTCYCLE}; @@ -1008,15 +1018,23 @@ sub GetSetData { ## no critic 'complexity' if($retry && $retc < $maxretries) { # neuer Retry im gleichen Zyklus (nicht wenn Verbraucher schalten) $hash->{HELPER}{RETRIES}++; - if($retc == $thold) { # Schwellenwert Leseversuche erreicht -> Cookie File löschen - Log3 ($name, 3, qq{$name - Threshold reached, delete cookie and retry in $sleepretry seconds ...}); - sleep $sleepexc; # Threshold exceed -> Retry mit Cookie löschen + my $cd = AttrVal($name, "cookieDelete", "auto"); + + if($retc == $thold || $cd =~ /Attempt/x) { # Schwellenwert Leseversuche erreicht -> Cookie File löschen + my $msg = qq{$name - Threshold reached, delete cookie file before retry...}; + + if($cd =~ /Attempt/x) { + $msg = qq{$name - force delete cookie file before retry...}; + } + + Log3 ($name, 3, $msg); + sleep $sleepretry; # Threshold exceed -> Retry mit Cookie löschen $exceed = 1; BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "RETRIES:".$hash->{HELPER}{RETRIES} ], 1); return "$name|$exceed|$newcycle|$errstate|$getp|$setp"; } - sleep $sleepretry; + sleep $sleepretry; goto &GetSetData; } @@ -1029,13 +1047,20 @@ sub GetSetData { ## no critic 'complexity' return "$name|$exceed|$newcycle|$errstate|$getp|$setp"; } } + + if(!@da) { + $state = "Warning - empty data received, values not current"; + if(AttrVal("global","language","EN") eq "DE") { + $state = "Warnung - leere Daten empfangen, Werte nicht aktuell"; + } + } } # Daten müssen als Einzeiler zurückgegeben werden - $st = encode_base64 ( $state, ""); + $st = encode_base64 ($state, ""); if(@da) { $lc = join "###", @da; - $lc = encode_base64 ( $lc, ""); + $lc = encode_base64 ($lc, ""); Log3 ($name, 3, "$name - data retrieved successfully."); } @@ -1171,20 +1196,25 @@ return 0; sub _getLiveData { ## no critic "not used" my $paref = shift; my $name = $paref->{name}; - my $ua = $paref->{ua}; # LWP Useragent + my $ua = $paref->{ua}; # LWP Useragent my $state = $paref->{state}; - my $daref = $paref->{daref}; # Referenz zum Datenarray + my $daref = $paref->{daref}; # Referenz zum Datenarray my ($reread,$retry,$errstate) = (0,0,0); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); - my $cts = fhemTimeLocal(0, 0, 0, $mday, $mon, $year); - my $offset = fhemTzOffset($cts); - my $time = int(($cts + $offset) * 1000); # add Timestamp in Millisekunden and UTC + my $cts = fhemTimeLocal(0, 0, 0, $mday, $mon, $year); + my $offset = fhemTzOffset($cts); + my $time = int(($cts + $offset) * 1000); # add Timestamp in Millisekunden and UTC + my $call = 'https://www.sunnyportal.com/homemanager?t='; + + if (AttrVal($name, "noHomeManager", 0)) { # Dashboard Seite abfragen wenn kein Home Manager vorhanden ist + $call = 'https://www.sunnyportal.com/Dashboard?t='; + } ($errstate,$state,$reread,$retry) = __dispatchGet ({ name => $name, ua => $ua, - call => 'https://www.sunnyportal.com/homemanager?t='.$time, + call => $call.$time, tag => "liveData", state => $state, fnaref => [ qw( extractLiveData ) ], @@ -1931,7 +1961,7 @@ sub ___analyzeData { ## no critic 'complexity' my $v5d = AttrVal($name, "verbose5Data", "none"); my $ad_content = encode("utf8", $ad->decoded_content); my $act = $hash->{HELPER}{RETRIES}; # Index aktueller Wiederholungsversuch - my $attstr = "Attempts read data again in $sleepretry seconds... ($act of $maxretries)"; # Log vorbereiten + my $attstr = "Attempts read data again in $sleepretry s ... ($act of $maxretries)"; # Log vorbereiten my $wm1e = qq{Updating of the live data was interrupted}; my $wm1d = qq{Die Aktualisierung der Live-Daten wurde unterbrochen}; @@ -2025,13 +2055,13 @@ sub ParseData { ## no critic my $name = $hash->{NAME}; my @da = (); - my ($errstate,$newcycle,$getp,$setp,$state,$exceed,$lc); + my $lc; - $exceed = $a[1]; - $newcycle = $a[2]; - $errstate = $a[3]; - $getp = $a[4]; - $setp = $a[5]; + my $exceed = $a[1]; + my $newcycle = $a[2]; + my $errstate = $a[3]; + my $getp = $a[4]; + my $setp = $a[5]; my $ac = $hash->{HELPER}{ACTCYCLE}; my $maxcycles = (controlParams $name)[1]; @@ -2061,7 +2091,7 @@ sub ParseData { ## no critic my $cycles = $hash->{HELPER}{ACTCYCLE}; my $ctime = int(($etime - $btime) / $cycles); # durchschnittliche Laufzeit für einen Zyklus - $state = decode_base64($a[6]); + my $state = decode_base64($a[6]); if($a[7]) { $lc = decode_base64($a[7]); @@ -2139,13 +2169,17 @@ return; ################################################################ sub finalCleanup { my $hash = shift; - + my $name = $hash->{NAME}; + delete($hash->{HELPER}{RUNNING_PID}); $hash->{HELPER}{GETTER} = "all"; $hash->{HELPER}{SETTER} = "none"; - #delcookiefile ($hash); + if(AttrVal($name, "cookieDelete", "auto") =~ /Run/x) { + Log3 ($name, 3, "$name - force delete cookie file"); + delcookiefile ($hash); + } return; } @@ -2213,11 +2247,18 @@ sub extractLiveData { ## no critic 'complexity' push @$daref, "${lv}_DirectConsumptionQuote:" .$live->{DirectConsumptionQuote}." %" if(defined $live->{DirectConsumptionQuote}); push @$daref, "${lv}_ModuleTemperature:" .$live->{ModuleTemperature}."" if(defined $live->{ModuleTemperature}); - push @$daref, "${lv}_OperationHealth:" .$live->{OperationHealth}."" if(defined $live->{OperationHealth}); push @$daref, "${lv}_Insolation:" .$live->{Insolation}."" if(defined $live->{Insolation}); push @$daref, "${lv}_WindSpeed:" .$live->{WindSpeed}."" if(defined $live->{WindSpeed}); push @$daref, "${lv}_EnvironmentTemperature:" .$live->{EnvironmentTemperature}."" if(defined $live->{EnvironmentTemperature}); + if($live->{OperationHealth}) { + my $o = "Ok: " .$live->{OperationHealth}{Ok}; + my $w = "Warning: ".$live->{OperationHealth}{Warning}; + my $e = "Error: " .$live->{OperationHealth}{Error}; + my $u = "Unknown: ".$live->{OperationHealth}{Unknown}; + push @$daref, "${lv}_OperationHealth: $o, $w, $e, $u"; + } + if($live->{ErrorMessages}[0]) { my @em; $errMsg = 1; @@ -2922,7 +2963,10 @@ sub deleteData { } for my $prl (keys %{$subs{$name}}) { # Provider die abgerufen wurden - my $lvl = $subs{$name}{$prl}{level} if($subs{$name}{$prl}{doit}); # Forum: https://forum.fhem.de/index.php/topic,102112.msg1078990.html#msg1078990 + my $lvl; + if($subs{$name}{$prl}{doit}) { + $lvl = $subs{$name}{$prl}{level}; # Forum: https://forum.fhem.de/index.php/topic,102112.msg1078990.html#msg1078990 + } if ($lvl) { $pbl .= "|^".$lvl."_"; } @@ -4086,6 +4130,25 @@ return;
+ +
  • cookieDelete
    + Defines the method of cookie management (deletion).
    + (default: auto) +
    + + + +

  • +
  • cookieLocation <Pfad/File>
    The path and filename of received Cookies.
    @@ -4384,6 +4447,25 @@ return;

  • + +
  • cookieDelete
    + Legt die Methode der Cookie Verwaltung (Löschung) fest.
    + (default: auto) +
    + + + +

  • +
  • cookieLocation <Pfad/File>
    Angabe von Pfad und Datei zur Abspeicherung des empfangenen Cookies.