diff --git a/fhem/contrib/DS_Starter/76_SMAPortal.pm b/fhem/contrib/DS_Starter/76_SMAPortal.pm
index 3522ee155..409fd6aa0 100644
--- a/fhem/contrib/DS_Starter/76_SMAPortal.pm
+++ b/fhem/contrib/DS_Starter/76_SMAPortal.pm
@@ -666,7 +666,10 @@ sub CallInfo {
Log3 ($name, 4, "$name - calculated timeout: $timeout");
}
- $hash->{HELPER}{ACTCYCLE} = 1 if(!$nc);
+ if(!$nc) {
+ $hash->{HELPER}{ACTCYCLE} = 1;
+ $hash->{HELPER}{CYCLEBTIME} = (gettimeofday())[0];
+ }
$hash->{HELPER}{RETRIES} = 1 if(!$nr);
my $ac = $hash->{HELPER}{ACTCYCLE};
@@ -696,24 +699,26 @@ sub controlParams {
# Voreinstellungen
my $timeout = 290; # Standard Timeout
my $definterval = 300; # Standard Interval
- my $buffer = 10; # Sicherheitspuffer zum nächsten Intervall
+ my $buffer = 5; # Sicherheitspuffer zum nächsten Intervall
- my $interval = AttrVal($name, "interval", $definterval); # 0 wenn manuell gesteuert
+ my $interval = AttrVal($name, "interval", $definterval); # 0 wenn manuell gesteuert
my $maxcycles = $defmaxcycles;
-
- if(!$interval) {
- return ($interval,$maxcycles,$timeout,"n.a.");
- }
- # Zeit eines Zyklus
+ # prognostizierte Zeit eines Zyklus
my $proctime = ($maxretries * 0.1);
- my $ctime = ($maxretries * $sleepretry) + $sleepexc + $proctime; # kalkulierte Zykluszeit
+ my $ctime = ($maxretries * $sleepretry) + $sleepexc + $proctime;
+ $ctime = ReadingsVal ($name, "lastCycleTime", $ctime);
+ $ctime = 10 if($ctime > 10); # Ausreißer ignorieren
+
+ if(!$interval) { # manueller Datenabruf
+ return ($interval,$maxcycles,$timeout,$ctime);
+ }
# max Anzahl Zyklen
$maxcycles = int(($interval - $buffer) / $ctime);
# Timeout kalkulieren
- my $timeout = int(($maxcycles * $ctime) + $proctime - $buffer);
+ $timeout = int(($maxcycles * $ctime) + $proctime - $buffer);
return ($interval,$maxcycles,$timeout,$ctime);
}
@@ -804,7 +809,7 @@ sub GetSetData { ## no cri
my $loginp = $ua->post('https://www.sunnyportal.com/Templates/Start.aspx',[$usernameField => $username, $passwordField => $password, "__EVENTTARGET" => $loginButton]);
- Log3 ($name, 4, "$name - ".$loginp->code);
+ Log3 ($name, 5, "$name - Login-Page return code: ".$loginp->code);
Log3 ($name, 5, "$name - Login-Page return: ".$loginp->content);
if($loginp->content =~ /Logincontrol1_ErrorLabel/ix) {
@@ -828,7 +833,7 @@ sub GetSetData { ## no cri
goto &GetSetData if($reread);
# Wiederholung Datenabruf innerhalb eines Cycle
- my $retc = $hash->{HELPER}{RETRIES};
+ my $retc = $hash->{HELPER}{RETRIES}; # aktuelle Retry-Zähler
if($setp eq "none" && $retry && $retc < $maxretries) { # neuer Retry im gleichen Zyklus (nicht wenn Verbraucher schalten)
$hash->{HELPER}{RETRIES}++;
@@ -1035,6 +1040,12 @@ sub ParseData { ## no critic
return;
}
+ # Laufzeit für einen Cycle berechnen
+ my $btime = $hash->{HELPER}{CYCLEBTIME};
+ my $etime = (gettimeofday())[0];
+ my $cycles = $hash->{HELPER}{ACTCYCLE};
+ my $ctime = int(($etime - $btime) / $cycles); # durchschnittliche Laufzeit für einen Zyklus
+
$state = decode_base64($a[6]);
$lc = decode_base64($a[7]);
$fc = decode_base64($a[8]) if($a[8]);
@@ -1046,6 +1057,7 @@ sub ParseData { ## no critic
my ($livedata_content,$forecast_content,$weatherdata_content,$consumerlivedata_content);
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content);
+
$livedata_content = decode_json($lc);
$forecast_content = decode_json($fc) if($fc);
$weatherdata_content = decode_json($wc) if($wc);
@@ -1066,89 +1078,92 @@ sub ParseData { ## no critic
my ($batteryin,$batteryout);
if($getp ne "none") {
- for my $k (keys %$livedata_content) {
- my $new_val = "";
- if (defined $livedata_content->{$k}) {
- if (($livedata_content->{$k} =~ m/ARRAY/i) || ($livedata_content->{$k} =~ m/HASH/ix)) {
- Log3 $name, 4, "$name - Livedata content \"$k\": ".($livedata_content->{$k});
- if($livedata_content->{$k} =~ m/ARRAY/ix) {
- my $hd0 = $livedata_content->{$k}[0];
- if(!defined $hd0) {
- next;
+ for my $k (keys %$livedata_content) {
+ my $new_val = "";
+ if (defined $livedata_content->{$k}) {
+ if (($livedata_content->{$k} =~ m/ARRAY/i) || ($livedata_content->{$k} =~ m/HASH/ix)) {
+ Log3 $name, 4, "$name - Livedata content \"$k\": ".($livedata_content->{$k});
+ if($livedata_content->{$k} =~ m/ARRAY/ix) {
+ my $hd0 = $livedata_content->{$k}[0];
+ if(!defined $hd0) {
+ next;
+ }
+ chomp $hd0;
+ $hd0 =~ s/[;']//gx;
+ $hd0 = encode("utf8", $hd0);
+ Log3 $name, 4, "$name - Livedata \"$k\": $hd0";
+ $new_val = $hd0;
}
- chomp $hd0;
- $hd0 =~ s/[;']//gx;
- $hd0 = encode("utf8", $hd0);
- Log3 $name, 4, "$name - Livedata \"$k\": $hd0";
- $new_val = $hd0;
+ } else {
+ $new_val = $livedata_content->{$k};
}
- } else {
- $new_val = $livedata_content->{$k};
- }
-
- if ($new_val && $k !~ /__type/ix) {
- if($k =~ /^FeedIn$/x) {
- $new_val = $new_val." W";
- $FeedIn_done = 1
- }
- if($k =~ /^GridConsumption$/x) {
- $new_val = $new_val." W";
- $GridConsumption_done = 1;
- }
- if($k =~ /^PV$/x) {
- $new_val = $new_val." W";
- $PV_done = 1;
- }
- if($k =~ /^AutarkyQuote$/x) {
- $new_val = $new_val." %";
- $AutarkyQuote_done = 1;
- }
- if($k =~ /^SelfConsumption$/x) {
- $new_val = $new_val." W";
- $SelfConsumption_done = 1;
- }
- if($k =~ /^SelfConsumptionQuote$/x) {
- $new_val = $new_val." %";
- $SelfConsumptionQuote_done = 1;
- }
- if($k =~ /^SelfSupply$/x) {
- $new_val = $new_val." W";
- $SelfSupply_done = 1;
- }
- if($k =~ /^TotalConsumption$/x) {
- $new_val = $new_val." W";
- }
- if($k =~ /^BatteryIn$/x) {
- $new_val = $new_val." W";
- $batteryin = 1;
- }
- if($k =~ /^BatteryOut$/x) {
- $new_val = $new_val." W";
- $batteryout = 1;
- }
-
- if($k =~ /^ErrorMessages$/x) { $errMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
- if($k =~ /^WarningMessages$/x) { $warnMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
- if($k =~ /^InfoMessages$/x) { $infoMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
+
+ if ($new_val && $k !~ /__type/ix) {
+ if($k =~ /^FeedIn$/x) {
+ $new_val = $new_val." W";
+ $FeedIn_done = 1
+ }
+ if($k =~ /^GridConsumption$/x) {
+ $new_val = $new_val." W";
+ $GridConsumption_done = 1;
+ }
+ if($k =~ /^PV$/x) {
+ $new_val = $new_val." W";
+ $PV_done = 1;
+ }
+ if($k =~ /^AutarkyQuote$/x) {
+ $new_val = $new_val." %";
+ $AutarkyQuote_done = 1;
+ }
+ if($k =~ /^SelfConsumption$/x) {
+ $new_val = $new_val." W";
+ $SelfConsumption_done = 1;
+ }
+ if($k =~ /^SelfConsumptionQuote$/x) {
+ $new_val = $new_val." %";
+ $SelfConsumptionQuote_done = 1;
+ }
+ if($k =~ /^SelfSupply$/x) {
+ $new_val = $new_val." W";
+ $SelfSupply_done = 1;
+ }
+ if($k =~ /^TotalConsumption$/x) {
+ $new_val = $new_val." W";
+ }
+ if($k =~ /^BatteryIn$/x) {
+ $new_val = $new_val." W";
+ $batteryin = 1;
+ }
+ if($k =~ /^BatteryOut$/x) {
+ $new_val = $new_val." W";
+ $batteryout = 1;
+ }
+
+ if($k =~ /^ErrorMessages$/x) { $errMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
+ if($k =~ /^WarningMessages$/x) { $warnMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
+ if($k =~ /^InfoMessages$/x) { $infoMsg = 1; $new_val = qq{Message got from SMA Sunny Portal:
$new_val};}
- Log3 ($name, 4, "$name - $k - $new_val");
- readingsBulkUpdate($hash, "L1_$k", $new_val);
+ Log3 ($name, 4, "$name - $k - $new_val");
+ readingsBulkUpdate($hash, "L1_$k", $new_val);
+ }
}
}
- }
+
+ readingsBulkUpdate($hash, "L1_FeedIn", "0 W") if(!$FeedIn_done);
+ readingsBulkUpdate($hash, "L1_GridConsumption", "0 W") if(!$GridConsumption_done);
+ readingsBulkUpdate($hash, "L1_PV", "0 W") if(!$PV_done);
+ readingsBulkUpdate($hash, "L1_AutarkyQuote", "0 %") if(!$AutarkyQuote_done);
+ readingsBulkUpdate($hash, "L1_SelfConsumption", "0 W") if(!$SelfConsumption_done);
+ readingsBulkUpdate($hash, "L1_SelfConsumptionQuote", "0 %") if(!$SelfConsumptionQuote_done);
+ readingsBulkUpdate($hash, "L1_SelfSupply", "0 W") if(!$SelfSupply_done);
+
+ if(defined $batteryin || defined $batteryout) {
+ readingsBulkUpdate($hash, "L1_BatteryIn", "0 W") if(!$batteryin);
+ readingsBulkUpdate($hash, "L1_BatteryOut", "0 W") if(!$batteryout);
+ }
+
+ readingsEndUpdate($hash, 1);
- readingsBulkUpdate($hash, "L1_FeedIn", "0 W") if(!$FeedIn_done);
- readingsBulkUpdate($hash, "L1_GridConsumption", "0 W") if(!$GridConsumption_done);
- readingsBulkUpdate($hash, "L1_PV", "0 W") if(!$PV_done);
- readingsBulkUpdate($hash, "L1_AutarkyQuote", "0 %") if(!$AutarkyQuote_done);
- readingsBulkUpdate($hash, "L1_SelfConsumption", "0 W") if(!$SelfConsumption_done);
- readingsBulkUpdate($hash, "L1_SelfConsumptionQuote", "0 %") if(!$SelfConsumptionQuote_done);
- readingsBulkUpdate($hash, "L1_SelfSupply", "0 W") if(!$SelfSupply_done);
- if(defined $batteryin || defined $batteryout) {
- readingsBulkUpdate($hash, "L1_BatteryIn", "0 W") if(!$batteryin);
- readingsBulkUpdate($hash, "L1_BatteryOut", "0 W") if(!$batteryout);
- }
- readingsEndUpdate($hash, 1);
}
readingsDelete($hash,"L1_ErrorMessages") if(!$errMsg);
@@ -1207,15 +1222,18 @@ sub ParseData { ## no critic
$op = ($op eq "auto")?"off (automatic)":$op;
readingsBulkUpdate($hash, "L3_${d}_Switch", $op);
}
- readingsBulkUpdate($hash, "state", $state);
- readingsBulkUpdate($hash, "summary", "$sum W");
+ readingsBulkUpdate($hash, "state" , $state);
+ readingsBulkUpdate($hash, "lastCycleTime", $ctime);
+ readingsBulkUpdate($hash, "summary" , "$sum W");
}
- readingsEndUpdate($hash, 1);
+ readingsEndUpdate($hash, 1);
delcookiefile ($hash);
delete($hash->{HELPER}{RUNNING_PID});
+
$hash->{HELPER}{GETTER} = "all";
$hash->{HELPER}{SETTER} = "none";
+
SPGRefresh($hash,0,1);
return;
@@ -1816,8 +1834,8 @@ return;
# $rd = Name des Zählerreadings
################################################################
sub handleCounter {
- my $name = shift;
- my $rd = shift;
+ my $name = shift;
+ my $rd = shift;
my $cstring = ReadingsVal($name, $rd, "");
my ($day,$count) = split(":", $cstring);