mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-22 08:11:44 +00:00
76_SMAPortal: contrib 1.5.0
git-svn-id: https://svn.fhem.de/fhem/trunk@19018 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
37825e24b2
commit
1af3883ad0
@ -84,10 +84,12 @@ use FHEM::Meta;
|
||||
use Data::Dumper;
|
||||
use Blocking;
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
use Time::Local;
|
||||
use LWP::UserAgent;
|
||||
use HTTP::Cookies;
|
||||
use JSON qw(decode_json);
|
||||
use MIME::Base64;
|
||||
use Encode;
|
||||
|
||||
# Run before module compilation
|
||||
BEGIN {
|
||||
@ -139,8 +141,9 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
our %vNotesIntern = (
|
||||
"1.4.0" => "22.03.2019 add function extractPlantData, DbLog_split, change L2 Readings",
|
||||
"1.3.0" => "18.03.2019 change module to use package FHEM::SMAPortal and Meta.pm, new sub setVersionInfo",
|
||||
"1.5.0" => "23.03.2019 add consumer data ",
|
||||
"1.4.0" => "22.03.2019 add function extractPlantData, DbLog_split, change L2 Readings ",
|
||||
"1.3.0" => "18.03.2019 change module to use package FHEM::SMAPortal and Meta.pm, new sub setVersionInfo ",
|
||||
"1.2.3" => "12.03.2019 make ready for 98_Installer.pm ",
|
||||
"1.2.2" => "11.03.2019 new Errormessage analyze added, make ready for Meta.pm ",
|
||||
"1.2.1" => "10.03.2019 behavior of state changed, commandref revised ",
|
||||
@ -533,7 +536,7 @@ sub GetData($) {
|
||||
# JSON Forecast Daten
|
||||
my $dl = AttrVal($name, "detailLevel", 1);
|
||||
if($dl > 1) {
|
||||
Log3 $name, 5, "$name - Getting forecast data now";
|
||||
Log3 $name, 4, "$name - Getting forecast data now";
|
||||
|
||||
my $forecast_page = $ua->get('https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData');
|
||||
Log3 $name, 5, "$name - Return Code: ".$forecast_page->code;
|
||||
@ -638,8 +641,8 @@ sub ParseData($) {
|
||||
for my $k (keys %$livedata_content) {
|
||||
my $new_val = "";
|
||||
if (defined $livedata_content->{$k}) {
|
||||
Log3 $name, 4, "$name - Livedata content \"$k\": ".($livedata_content->{$k});
|
||||
if (($livedata_content->{$k} =~ m/ARRAY/i) || ($livedata_content->{$k} =~ m/HASH/i)) {
|
||||
Log3 $name, 4, "$name - Livedata content \"$k\": ".($livedata_content->{$k});
|
||||
if($livedata_content->{$k} =~ m/ARRAY/i) {
|
||||
my $hd0 = Dumper($livedata_content->{$k}[0]);
|
||||
if(!$hd0) {
|
||||
@ -648,7 +651,7 @@ sub ParseData($) {
|
||||
chomp $hd0;
|
||||
$hd0 =~ s/[;']//g;
|
||||
$hd0 = ($hd0 =~ /^undef$/)?"none":$hd0;
|
||||
Log3 $name, 4, "$name - Livedata ARRAY content \"$k\": $hd0";
|
||||
Log3 $name, 4, "$name - Livedata \"$k\": $hd0";
|
||||
$new_val = $hd0;
|
||||
}
|
||||
} else {
|
||||
@ -683,6 +686,7 @@ sub ParseData($) {
|
||||
# Auswertung der Forecast Daten
|
||||
extractForecastData($hash,$forecast_content);
|
||||
extractPlantData($hash,$forecast_content);
|
||||
extractConsumerData($hash,$forecast_content);
|
||||
}
|
||||
|
||||
if ($weatherdata_content && $weatherdata_content !~ m/undefined/i) {
|
||||
@ -805,9 +809,8 @@ sub extractForecastData($$) {
|
||||
my $current_day = (localtime)[3];
|
||||
|
||||
# Loop through all forecast objects
|
||||
# Energie wird als "J" geliefert, Wh = J / 3600
|
||||
foreach my $fc_obj (@{$forecast->{'ForecastSeries'}}) {
|
||||
|
||||
# Log3 $name, 4, "$name - Forecast data: ".Dumper $fc_obj;
|
||||
# Example for DateTime: 2016-02-15T23:00:00
|
||||
my $fc_datetime = $fc_obj->{'TimeStamp'}->{'DateTime'};
|
||||
|
||||
@ -816,7 +819,6 @@ sub extractForecastData($$) {
|
||||
my $fc_uts = POSIX::mktime( 0, 0, $fc_hour, $fc_day, $fc_month - 1, $fc_year - 1900 );
|
||||
my $fc_diff_seconds = $fc_uts - time + 3600; # So we go above 0 for the current hour
|
||||
my $fc_diff_hours = int( $fc_diff_seconds / 3600 );
|
||||
#Log3 $hash->{NAME}, 3, "Found $fc_datetime, diff $fc_diff_seconds seconds, $fc_diff_hours hours.";
|
||||
|
||||
# Don't use old data
|
||||
next if $fc_diff_seconds < 0;
|
||||
@ -852,14 +854,14 @@ sub extractForecastData($$) {
|
||||
my $time_str = "ThisHour";
|
||||
$time_str = "NextHour".sprintf("%02d", $obj_nr) if($fc_diff_hours>0);
|
||||
if($time_str =~ /NextHour/ && $dl >= 4) {
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}_Time", $fc_obj->{'TimeStamp'}->{'DateTime'} );
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}_Time", UTC2LocalString($hash,$fc_obj->{'TimeStamp'}->{'DateTime'}) );
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}_PvMeanPower", int( $fc_obj->{'PvMeanPower'}->{'Amount'} ) );
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}_Consumption", int( $fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600 ) );
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}_IsConsumptionRecommended", ($fc_obj->{'IsConsumptionRecommended'} ? "yes" : "no") );
|
||||
readingsBulkUpdate( $hash, "L4_${time_str}", int( $fc_obj->{'PvMeanPower'}->{'Amount'} - $fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600 ) );
|
||||
}
|
||||
if($time_str =~ /ThisHour/ && $dl >= 2) {
|
||||
readingsBulkUpdate( $hash, "L2_${time_str}_Time", $fc_obj->{'TimeStamp'}->{'DateTime'} );
|
||||
readingsBulkUpdate( $hash, "L2_${time_str}_Time", UTC2LocalString($hash,$fc_obj->{'TimeStamp'}->{'DateTime'}) );
|
||||
readingsBulkUpdate( $hash, "L2_${time_str}_PvMeanPower", int( $fc_obj->{'PvMeanPower'}->{'Amount'} ) );
|
||||
readingsBulkUpdate( $hash, "L2_${time_str}_Consumption", int( $fc_obj->{'ConsumptionForecast'}->{'Amount'} / 3600 ) );
|
||||
readingsBulkUpdate( $hash, "L2_${time_str}_IsConsumptionRecommended", ($fc_obj->{'IsConsumptionRecommended'} ? "yes" : "no") );
|
||||
@ -927,7 +929,7 @@ sub extractWeatherData($$) {
|
||||
chomp $hd0;
|
||||
$hd0 =~ s/[;']//g;
|
||||
$hd0 = ($hd0 =~ /^undef$/)?"none":$hd0;
|
||||
Log3 $name, 4, "$name - Weatherdata HASH content \"$k $i\": $hd0";
|
||||
Log3 $name, 4, "$name - Weatherdata \"$k $i\": $hd0";
|
||||
next if($i =~ /^WeatherIcon$/);
|
||||
$new_val = $hd0;
|
||||
|
||||
@ -982,8 +984,8 @@ sub extractPlantData($$) {
|
||||
if($ppp && $dl >= 2) {
|
||||
$amount = $forecast->{'PlantPeakPower'}{'Amount'};
|
||||
$unit = $forecast->{'PlantPeakPower'}{'StandardUnit'}{'Symbol'};
|
||||
Log3 $name, 4, "$name - Plantdata HASH content \"PlantPeakPower Amount\": $amount";
|
||||
Log3 $name, 4, "$name - Plantdata HASH content \"PlantPeakPower Symbol\": $unit";
|
||||
Log3 $name, 4, "$name - Plantdata \"PlantPeakPower Amount\": $amount";
|
||||
Log3 $name, 4, "$name - Plantdata \"PlantPeakPower Symbol\": $unit";
|
||||
}
|
||||
|
||||
readingsBulkUpdate($hash, "L2_PlantPeakPower", "$amount $unit");
|
||||
@ -993,6 +995,85 @@ sub extractPlantData($$) {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
## Auswertung Consumer Data
|
||||
################################################################
|
||||
sub extractConsumerData($$) {
|
||||
my ($hash,$forecast) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my %consumers;
|
||||
my ($key,$val);
|
||||
|
||||
my $dl = AttrVal($name, "detailLevel", 1);
|
||||
if($dl <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
# Schleife über alle Consumer Objekte
|
||||
my $i = 0;
|
||||
foreach my $c (@{$forecast->{'Consumers'}}) {
|
||||
$consumers{"${i}_ConsumerName"} = encode("utf8", $c->{'ConsumerName'} );
|
||||
$consumers{"${i}_ConsumerOid"} = $c->{'ConsumerOid'};
|
||||
$i++;
|
||||
}
|
||||
|
||||
if(%consumers && $forecast->{'ForecastTimeframes'}) {
|
||||
# es sind Vorhersagen zu geplanten Verbraucherschaltzeiten vorhanden
|
||||
foreach my $c (@{$forecast->{'ForecastTimeframes'}{'PlannedTimeFrames'}}) {
|
||||
my $deviceOid = $c->{'DeviceOid'};
|
||||
my $timeFrameStart = UTC2LocalString($hash,$c->{'TimeFrameStart'}{'DateTime'}); # wandele UTC Time zu lokaler Zeit
|
||||
my $timeFrameEnd = UTC2LocalString($hash,$c->{'TimeFrameEnd'}{'DateTime'}); # wandele UTC Time zu lokaler Zeit
|
||||
my $tz = $c->{'TimeFrameStart'}{'Kind'};
|
||||
foreach my $k (keys(%consumers)) {
|
||||
$val = $consumers{$k};
|
||||
if($val eq $deviceOid) {
|
||||
$k =~ /^(\d+)_.*$/;
|
||||
my $lfn = $1;
|
||||
# $consumer = $consumers{"${lfn}_ConsumerName"};
|
||||
$consumers{"${lfn}_PlannedOpTimeStart"} = $timeFrameStart;
|
||||
$consumers{"${lfn}_PlannedOpTimeEnd"} = $timeFrameEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(%consumers) {
|
||||
foreach my $key (keys(%consumers)) {
|
||||
Log3 $name, 4, "$name - Consumer data \"$key\": ".$consumers{$key};
|
||||
if($key =~ /ConsumerName/ && $dl >= 3) {
|
||||
$key =~ /^(\d+)_.*$/;
|
||||
my $lfn = $1;
|
||||
my $cn = $consumers{"${lfn}_ConsumerName"}; # Verbrauchername
|
||||
my $pos = $consumers{"${lfn}_PlannedOpTimeStart"}; # geplanter Start
|
||||
my $poe = $consumers{"${lfn}_PlannedOpTimeEnd"}; # geplantes Ende
|
||||
my $rb = "L3_${cn}_PlannedOpTimeBegin";
|
||||
my $re = "L3_${cn}_PlannedOpTimeEnd";
|
||||
my $rp = "L3_${cn}_Planned";
|
||||
if($pos) {
|
||||
readingsBulkUpdate($hash, $rb, $pos);
|
||||
readingsBulkUpdate($hash, $rp, "yes");
|
||||
} else {
|
||||
readingsBulkUpdate($hash, $rb, "undefined");
|
||||
readingsBulkUpdate($hash, $rp, "no");
|
||||
}
|
||||
if($poe) {
|
||||
readingsBulkUpdate($hash, $re, $poe);
|
||||
} else {
|
||||
readingsBulkUpdate($hash, $re, "undefined");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# sortiert eine Liste von Versionsnummern x.x.x
|
||||
# Schwartzian Transform and the GRT transform
|
||||
@ -1100,7 +1181,7 @@ sub analivedat($$) {
|
||||
chomp $hd0;
|
||||
$hd0 =~ s/[;']//g;
|
||||
$hd0 = ($hd0 =~ /^undef$/)?"none":$hd0;
|
||||
Log3 $name, 4, "$name - livedata ARRAY content \"$k\": $hd0";
|
||||
# Log3 $name, 4, "$name - livedata ARRAY content \"$k\": $hd0";
|
||||
$new_val = $hd0;
|
||||
}
|
||||
} else {
|
||||
@ -1144,6 +1225,31 @@ sub retrygetdata($) {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# UTC in lokale Zeit umwandeln
|
||||
################################################################
|
||||
sub UTC2LocalString($$) {
|
||||
my ($hash,$t) = @_;
|
||||
$t =~ s/T/ /;
|
||||
my ($datehour, $rest) = split(/:/,$t,2);
|
||||
my ($year, $month, $day, $hour) = $datehour =~ /(\d+)-(\d\d)-(\d\d)\s+(\d\d)/;
|
||||
|
||||
# proto: $time = timegm($sec,$min,$hour,$mday,$mon,$year);
|
||||
my $epoch = timegm (0,0,$hour,$day,$month-1,$year);
|
||||
|
||||
# proto: ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
||||
my ($lyear,$lmonth,$lday,$lhour,$isdst) = (localtime($epoch))[5,4,3,2,-1];
|
||||
|
||||
$lyear += 1900; # year is 1900 based
|
||||
$lmonth++; # month number is zero based
|
||||
|
||||
if(AttrVal("global","language","EN") eq "DE") {
|
||||
return (sprintf("%02d.%02d.%04d %02d:%s", $lday,$lmonth,$lyear,$lhour,$rest));
|
||||
} else {
|
||||
return (sprintf("%04d-%02d-%02d %02d:%s", $lyear,$lmonth,$lday,$lhour,$rest));
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -1281,7 +1387,7 @@ return;
|
||||
<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>L2</b> </td><td>- wie L1 und zusätzlich Prognose der aktuellen und nächsten 4 Stunden </td></tr>
|
||||
<tr><td> <b>L3</b> </td><td>- wie L2 und zusätzlich Prognosedaten des Resttages und Folgetages </td></tr>
|
||||
<tr><td> <b>L3</b> </td><td>- wie L2 und zusätzlich Prognosedaten des Resttages, des Folgetages und der geplanten Schaltzeiten für Verbraucher </td></tr>
|
||||
<tr><td> <b>L4</b> </td><td>- wie L3 und zusätzlich die detaillierte Prognose der nächsten 24 Stunden </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
@ -1365,11 +1471,13 @@ return;
|
||||
"FHEM": 5.00918799,
|
||||
"perl": 5.014,
|
||||
"JSON": 0,
|
||||
"Encode": 0,
|
||||
"POSIX": 0,
|
||||
"Data::Dumper": 0,
|
||||
"Blocking": 0,
|
||||
"GPUtils": 0,
|
||||
"Time::HiRes": 0,
|
||||
"Time::Local": 0,
|
||||
"LWP": 0,
|
||||
"HTTP::Cookies": 0,
|
||||
"FHEM::Meta": 0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user