mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-20 07:16:03 +00:00
76_SMAPortal: contrib 2.9.0
git-svn-id: https://svn.fhem.de/fhem/trunk@22090 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
66adddc54d
commit
180f71a245
@ -25,7 +25,7 @@
|
||||
#
|
||||
# Credits (Thanks to all!):
|
||||
# Brun von der Gönne <brun at goenne dot de> : author of 98_SHM.pm
|
||||
# BerndArnold : author of 98_SHMForecastRelative.pm
|
||||
# BerndArnold : author of 98_SHMForecastRelative.pm / add get statistic data
|
||||
# Wzut/XGuide : creation of SMAPortal graphics
|
||||
#
|
||||
# FHEM Forum: http://forum.fhem.de/index.php/topic,27667.0.html
|
||||
@ -134,6 +134,7 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"2.9.0" => "01.06.2020 add get today statistic data ",
|
||||
"2.8.1" => "31.05.2020 attribute timeout, maxCallCycle deleted ",
|
||||
"2.8.0" => "31.05.2020 refactoring process logic, attribute cookielifetime & getDataRetries deleted, command delCookieFile deleted ".
|
||||
"new attribute maxCallCycle ",
|
||||
@ -211,7 +212,7 @@ sub Initialize {
|
||||
"interval ".
|
||||
"showPassInLog:1,0 ".
|
||||
"userAgent ".
|
||||
"verbose5Data:none,liveData,weatherData,forecastData,consumerLiveData,consumerDayData,consumerMonthData,consumerYearData ".
|
||||
"verbose5Data:none,balanceData,liveData,weatherData,forecastData,consumerLiveData,consumerDayData,consumerMonthData,consumerYearData ".
|
||||
$readingFnAttributes;
|
||||
|
||||
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval' # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html)
|
||||
@ -708,7 +709,7 @@ sub controlParams {
|
||||
my $proctime = ($maxretries * 0.1);
|
||||
my $ctime = ($maxretries * $sleepretry) + $sleepexc + $proctime;
|
||||
$ctime = ReadingsVal ($name, "lastCycleTime", $ctime);
|
||||
$ctime = 10 if($ctime > 10); # Ausreißer ignorieren
|
||||
$ctime = 7 if($ctime > 7); # Ausreißer ignorieren
|
||||
|
||||
if(!$interval) { # manueller Datenabruf
|
||||
return ($interval,$maxcycles,$timeout,$ctime);
|
||||
@ -739,7 +740,8 @@ sub GetSetData { ## no cri
|
||||
my $state = "ok";
|
||||
my ($reread,$retry) = (0,0);
|
||||
my ($exceed,$newcycle) = (0,0);
|
||||
my ($forecast_content,$weatherdata_content,$consumerlivedata_content,$ccdaydata_content,$ccmonthdata_content) = ("","","","","");
|
||||
my ($forecast_content,$weatherdata_content,$consumerlivedata_content) = ("","","");
|
||||
my ($balancedataday_content,$ccdaydata_content,$ccmonthdata_content) = ("","","");
|
||||
my ($livedata_content,$d,$op);
|
||||
|
||||
if($setp ne "none") {
|
||||
@ -752,6 +754,9 @@ sub GetSetData { ## no cri
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
|
||||
# $ua->add_handler( request_send => sub { shift->dump; return } ); # for debugging
|
||||
# $ua->add_handler( response_done => sub { shift->dump; return } );
|
||||
|
||||
# Header Daten
|
||||
$ua->default_header("Accept" => "*/*",
|
||||
"Accept-Encoding" => "gzip, deflate, br",
|
||||
@ -893,14 +898,34 @@ sub GetSetData { ## no cri
|
||||
#########################
|
||||
if($getp ne "none") {
|
||||
|
||||
my $dl = AttrVal($name, "detailLevel", 1); # selcted Detail Level
|
||||
|
||||
# JSON Wetterdaten
|
||||
Log3 ($name, 4, "$name - Getting weather data");
|
||||
my $weatherdata = $ua->get('https://www.sunnyportal.com/Dashboard/Weather');
|
||||
$weatherdata_content = $weatherdata->content;
|
||||
Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($weatherdata_content)) if($v5d eq "weatherData");
|
||||
|
||||
|
||||
# JSON Statistic Data Tag (anchorTime beachten !)
|
||||
Log3 ($name, 4, "$name - Getting statistic day data");
|
||||
my $req = HTTP::Request->new( 'POST', 'https://www.sunnyportal.com/FixedPages/HoManEnergyRedesign.aspx/GetLegendWithValues' );
|
||||
|
||||
my $anchort = int ($time / 1000); # anchorTime -> abzurufendes Datum
|
||||
my $tab = 1; # Tab 1 -> Tag , 2->Monat, 3->Jahr, 4->Gesamt
|
||||
my $cont = qq{"tabNumber":$tab,"anchorTime":$anchort};
|
||||
|
||||
$req->header ( "Content-Type" => "application/json; charset=utf-8" );
|
||||
$req->header ( "Content-Length" => 39 );
|
||||
$req->content ( "{$cont}" );
|
||||
|
||||
my $res = $ua->request( $req );
|
||||
$balancedataday_content = $res->content;
|
||||
|
||||
Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($balancedataday_content)) if($v5d eq "balanceData");
|
||||
|
||||
|
||||
# JSON Forecast Daten
|
||||
my $dl = AttrVal($name, "detailLevel", 1);
|
||||
if($dl > 1) {
|
||||
Log3 ($name, 4, "$name - Getting forecast data");
|
||||
|
||||
@ -989,9 +1014,10 @@ sub GetSetData { ## no cri
|
||||
}
|
||||
|
||||
# Daten müssen als Einzeiler zurückgegeben werden
|
||||
my ($st,$lc,$fc,$wc,$cl,$cd,$cm,$cy) = ("","","","","","","","");
|
||||
my ($st,$bcd,$lc,$fc,$wc,$cl,$cd,$cm,$cy) = ("","","","","","","","","");
|
||||
$st = encode_base64 ( $state,"");
|
||||
$lc = encode_base64($livedata_content,"");
|
||||
$bcd = encode_base64 ( $balancedataday_content, "" ) if($balancedataday_content);
|
||||
$lc = encode_base64 ( $livedata_content, "" ) if($livedata_content);
|
||||
$fc = encode_base64 ( $forecast_content, "" ) if($forecast_content);
|
||||
$wc = encode_base64 ( $weatherdata_content, "" ) if($weatherdata_content);
|
||||
$cl = encode_base64 ( $consumerlivedata_content, "" ) if($consumerlivedata_content);
|
||||
@ -999,7 +1025,7 @@ sub GetSetData { ## no cri
|
||||
$cm = encode_base64 ( $ccmonthdata_content, "" ) if($ccmonthdata_content);
|
||||
$cy = encode_base64 ( $ccyeardata_content, "" ) if($ccyeardata_content);
|
||||
|
||||
return "$name|$exceed|$newcycle|$login_state|$getp|$setp|$st|$lc|$fc|$wc|$cl|$cd|$cm|$cy";
|
||||
return "$name|$exceed|$newcycle|$login_state|$getp|$setp|$st|$lc|$fc|$wc|$cl|$cd|$cm|$cy|$bcd";
|
||||
}
|
||||
|
||||
################################################################
|
||||
@ -1011,7 +1037,7 @@ sub ParseData { ## no critic
|
||||
my $hash = $defs{$a[0]};
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my ($login_state,$newcycle,$getp,$setp,$fc,$wc,$cl,$cd,$cm,$cy,$lc,$state,$exceed);
|
||||
my ($login_state,$newcycle,$getp,$setp,$state,$exceed);
|
||||
|
||||
$exceed = $a[1];
|
||||
$newcycle = $a[2];
|
||||
@ -1047,24 +1073,18 @@ sub ParseData { ## no critic
|
||||
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]);
|
||||
$wc = decode_base64($a[9]) if($a[9]);
|
||||
$cl = decode_base64($a[10]) if($a[10]);
|
||||
$cd = decode_base64($a[11]) if($a[11]);
|
||||
$cm = decode_base64($a[12]) if($a[12]);
|
||||
$cy = decode_base64($a[13]) if($a[13]);
|
||||
|
||||
my ($livedata_content,$forecast_content,$weatherdata_content,$consumerlivedata_content);
|
||||
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content);
|
||||
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content,$balancedataday_content);
|
||||
|
||||
$livedata_content = decode_json($lc);
|
||||
$forecast_content = decode_json($fc) if($fc);
|
||||
$weatherdata_content = decode_json($wc) if($wc);
|
||||
$consumerlivedata_content = decode_json($cl) if($cl);
|
||||
$ccdaydata_content = decode_json($cd) if($cd);
|
||||
$ccmonthdata_content = decode_json($cm) if($cm);
|
||||
$ccyeardata_content = decode_json($cy) if($cy);
|
||||
$livedata_content = decode_json( decode_base64($a[7]) ) if($a[7]);
|
||||
$forecast_content = decode_json( decode_base64($a[8]) ) if($a[8]);
|
||||
$weatherdata_content = decode_json( decode_base64($a[9]) ) if($a[9]);
|
||||
$consumerlivedata_content = decode_json( decode_base64($a[10]) ) if($a[10]);
|
||||
$ccdaydata_content = decode_json( decode_base64($a[11]) ) if($a[11]);
|
||||
$ccmonthdata_content = decode_json( decode_base64($a[12]) ) if($a[12]);
|
||||
$ccyeardata_content = decode_json( decode_base64($a[13]) ) if($a[13]);
|
||||
$balancedataday_content = decode_json( decode_base64($a[14]) ) if($a[14]);
|
||||
|
||||
my $dl = AttrVal($name, "detailLevel", 1);
|
||||
delread($hash, $dl+1);
|
||||
@ -1202,6 +1222,11 @@ sub ParseData { ## no critic
|
||||
extractWeatherData ($hash,$weatherdata_content);
|
||||
}
|
||||
|
||||
if ($balancedataday_content && $balancedataday_content !~ m/undefined/ix) {
|
||||
# Auswertung Statistik Daten Tag
|
||||
extractStatisticData ($hash,$balancedataday_content,"Day");
|
||||
}
|
||||
|
||||
my $pv = ReadingsNum($name, "L1_PV" , 0);
|
||||
my $fi = ReadingsNum($name, "L1_FeedIn" , 0);
|
||||
my $gc = ReadingsNum($name, "L1_GridConsumption", 0);
|
||||
@ -1437,8 +1462,6 @@ sub extractWeatherData {
|
||||
|
||||
Log3 ($name, 4, "$name - ##### extracting weather data #### ");
|
||||
|
||||
my $dl = AttrVal($name, "detailLevel", 1);
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
for my $k (keys %$weather) {
|
||||
@ -1488,6 +1511,58 @@ sub extractWeatherData {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Auswertung Statistic Daten
|
||||
# $period = Day | Month | Year
|
||||
################################################################
|
||||
sub extractStatisticData {
|
||||
my ($hash,$statistic,$period) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $sd;
|
||||
my @da = ();
|
||||
|
||||
Log3 ($name, 4, "$name - ##### extracting statistic data #### ");
|
||||
|
||||
my %ch = ( # Zieldatenhash
|
||||
Energy => 1,
|
||||
FeedIn => 1,
|
||||
GridConsumption => 1,
|
||||
SelfConsumption => 1,
|
||||
SelfSupply => 1,
|
||||
DirectConsumption => 1,
|
||||
TotalConsumption => 1,
|
||||
BackupOut => 1,
|
||||
BackupIn => 1,
|
||||
SelfConsumptionRate => 1,
|
||||
DirectConsumptionRate => 1,
|
||||
AutarkyRate => 1,
|
||||
);
|
||||
|
||||
if(ref $statistic eq "HASH") {
|
||||
$sd = decode_json ($statistic->{d});
|
||||
}
|
||||
|
||||
if($sd && ref $sd eq "ARRAY") {
|
||||
for my $a (@$sd) { # jedes ARRAY-Element ist ein HASH
|
||||
my $k = $a->{Key};
|
||||
my $v = $a->{Value};
|
||||
push @da, "$k:$v" if(defined $ch{$k});
|
||||
}
|
||||
}
|
||||
|
||||
readingsBeginUpdate($hash); # generiere Readings
|
||||
|
||||
for my $elem (@da) {
|
||||
my ($rn,$rval) = split ":", $elem;
|
||||
readingsBulkUpdate($hash, "L1_Today_".$rn, $rval);
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
## Auswertung Anlagendaten
|
||||
################################################################
|
||||
@ -1843,7 +1918,8 @@ sub handleCounter {
|
||||
if(!$day || $day != $mday) {
|
||||
$count = 0;
|
||||
$day = $mday;
|
||||
Log3 ($name, 2, qq{$name - reset counter "$rd" to >0< });
|
||||
Log3 ($name, 2, qq{$name - reset counter "$rd" to >0< }) if(!$defs{$name}->{HELPER}{$rd});
|
||||
$defs{$name}->{HELPER}{$rd} = 1; # nur im fork setzen um doppelten Logeintrag zu vermeiden
|
||||
}
|
||||
$count++;
|
||||
$cstring = "$rd:$day:$count";
|
||||
@ -2950,7 +3026,7 @@ return;
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||
<tr><td> <b>L1</b> </td><td>- only live data and weather data are generated. </td></tr>
|
||||
<tr><td> <b>L1</b> </td><td>- live data, statistic day data and weather data are generated. </td></tr>
|
||||
<tr><td> <b>L2</b> </td><td>- as L1 and additional forecast of the current data, the data of the next 4 hours as well as PV-Generation / Consumption the rest of day and the next day </td></tr>
|
||||
<tr><td> <b>L3</b> </td><td>- as L2 and additional forecast of the planned switch-on times of consumers, whose current state and energy data as well as their battery usage data </td></tr>
|
||||
<tr><td> <b>L4</b> </td><td>- as L3 and additional a detailed forecast of the next 24 hours </td></tr>
|
||||
@ -3015,6 +3091,7 @@ return;
|
||||
<ul>
|
||||
<ul>
|
||||
<li>Live-Daten (Verbrauch und PV-Erzeugung) </li>
|
||||
<li>Tagesstatistiken </li>
|
||||
<li>Batteriedaten (In/Out) sowie Nutzungsdaten durch Verbraucher </li>
|
||||
<li>Wetter-Daten von SMA für den Anlagenstandort </li>
|
||||
<li>Prognosedaten (Verbrauch und PV-Erzeugung) inklusive Verbraucherempfehlung </li>
|
||||
@ -3144,7 +3221,7 @@ return;
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||
<tr><td> <b>L1</b> </td><td>- nur Live-Daten und Wetter-Daten werden generiert. </td></tr>
|
||||
<tr><td> <b>L1</b> </td><td>- Live-Daten, Tagesstatistiken und Wetter-Daten werden generiert. </td></tr>
|
||||
<tr><td> <b>L2</b> </td><td>- wie L1 und zusätzlich Prognose der aktuellen und nächsten 4 Stunden sowie PV-Erzeugung / Verbrauch des Resttages und des Folgetages </td></tr>
|
||||
<tr><td> <b>L3</b> </td><td>- wie L2 und zusätzlich Prognosedaten der geplanten Einschaltzeiten von Verbrauchern, deren aktueller Status und Energiedaten sowie Batterie-Nutzungsdaten</td></tr>
|
||||
<tr><td> <b>L4</b> </td><td>- wie L3 und zusätzlich die detaillierte Prognose der nächsten 24 Stunden </td></tr>
|
||||
|
Loading…
x
Reference in New Issue
Block a user