2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

76_SMAPortal: contrib 3.7.0

git-svn-id: https://svn.fhem.de/fhem/trunk@23187 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2020-11-19 21:00:39 +00:00
parent fb8f72056d
commit 7da5bed44b

View File

@ -137,7 +137,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"3.7.0" => "18.11.2020 add new consumer management for switched sockets and EVCharger ", "3.7.0" => "19.11.2020 add new consumer management for switched sockets and EVCharger ",
"3.6.5" => "12.11.2020 verbose5data switchConsumer, more preselected user agents ", "3.6.5" => "12.11.2020 verbose5data switchConsumer, more preselected user agents ",
"3.6.4" => "11.11.2020 preselect the user agent randomly, set min. interval to 180 s ", "3.6.4" => "11.11.2020 preselect the user agent randomly, set min. interval to 180 s ",
"3.6.3" => "05.11.2020 fix only four consumer are shown in set command drop down list ", "3.6.3" => "05.11.2020 fix only four consumer are shown in set command drop down list ",
@ -179,43 +179,6 @@ my %vNotesIntern = (
"2.6.0" => "20.04.2020 change package config, improve cookie management, decouple switch consumers from livedata retrieval ". "2.6.0" => "20.04.2020 change package config, improve cookie management, decouple switch consumers from livedata retrieval ".
"some improvements according to PBP ", "some improvements according to PBP ",
"2.5.0" => "25.08.2019 change switch consumer to on<->automatic only in graphic overview, Forum: https://forum.fhem.de/index.php/topic,102112.msg969002.html#msg969002", "2.5.0" => "25.08.2019 change switch consumer to on<->automatic only in graphic overview, Forum: https://forum.fhem.de/index.php/topic,102112.msg969002.html#msg969002",
"2.4.5" => "22.08.2019 fix some warnings, Forum: https://forum.fhem.de/index.php/topic,102112.msg968829.html#msg968829 ",
"2.4.4" => "11.07.2019 fix consinject to show multiple consumer icons if planned ",
"2.4.3" => "07.07.2019 change header design of portal graphics again ",
"2.4.2" => "02.07.2019 change header design of portal graphics ",
"2.4.1" => "01.07.2019 replace space in consumer name by a valid sign for reading creation ",
"2.4.0" => "26.06.2019 support for FTUI-Widget ",
"2.3.7" => "24.06.2019 replace suggestIcon by consumerAdviceIcon ",
"2.3.6" => "21.06.2019 revise commandref ",
"2.3.5" => "20.06.2019 subroutine consinject added to pv, pvco style ",
"2.3.4" => "19.06.2019 change some readingnames, delete L4_plantOid, next04hours_state ",
"2.3.3" => "16.06.2019 change verbose 4 output, fix warning if no weather info was got ",
"2.3.2" => "14.06.2019 add request string to verbose 5, add battery data to live and historical consumer data ",
"2.3.1" => "13.06.2019 switch Credentials read from RAM to verbose 4, changed W/h->Wh and kW/h->kWh in PortalAsHtml ",
"2.3.0" => "12.06.2019 add set on,off,automatic cmd for controlled devices ",
"2.2.0" => "10.06.2019 relocate RestOfDay and Tomorrow data from level 3 to level 2, change readings to start all with uppercase, ".
"add consumer energy data of current day/month/year, new attribute \"verbose5Data\" ",
"2.1.2" => "08.06.2019 correct planned time of consumer in PortalAsHtml if planned time is at next day ",
"2.1.1" => "08.06.2019 add units to values, some bugs fixed ",
"2.1.0" => "07.06.2019 add informations about consumer switch and power state ",
"2.0.0" => "03.06.2019 designed for SMAPortalSPG graphics device ",
"1.8.0" => "27.05.2019 redesign of SMAPortal graphics by Wzut/XGuide ",
"1.7.1" => "01.05.2019 PortalAsHtml: use of colored svg-icons possible ",
"1.7.0" => "01.05.2019 code change of PortalAsHtml, new attributes \"portalGraphicColor\" and \"portalGraphicStyle\" ",
"1.6.0" => "29.04.2019 function PortalAsHtml ",
"1.5.5" => "22.04.2019 fix readings for BattryOut and BatteryIn ",
"1.5.4" => "26.03.2019 delete L1_InfoMessages if no info occur ",
"1.5.3" => "26.03.2019 delete L1_ErrorMessages, L1_WarningMessages if no errors or warnings occur ",
"1.5.2" => "25.03.2019 prevent module from deactivation in case of unavailable Meta.pm ",
"1.5.1" => "24.03.2019 fix \$VAR1 problem Forum: #27667.msg922983.html#msg922983 ",
"1.5.0" => "23.03.2019 add consumer data ",
"1.4.0" => "22.03.2019 add function extractPlantMasterData, 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 ",
"1.2.0" => "09.03.2019 integrate weather data, minor fixes ",
"1.1.0" => "09.03.2019 make get data more stable, new attribute 'getDataRetries' ",
"1.0.0" => "03.03.2019 initial " "1.0.0" => "03.03.2019 initial "
); );
@ -1357,7 +1320,7 @@ sub _manageConsumerByEnergy {
call => 'https://www.sunnyportal.com/HoMan/Consumer/Semp/$oid', call => 'https://www.sunnyportal.com/HoMan/Consumer/Semp/$oid',
tag => $tag, tag => $tag,
state => $state, state => $state,
fnaref => [ qw( extractConsumerByEnergyData ) ], fnaref => [ qw( extractManageConsumerByEnergy ) ],
fields => \%fields, fields => \%fields,
content => $cont, content => $cont,
addon => "$d:$susyid:$op", # optionales Addon für aufzurufende Funktion addon => "$d:$susyid:$op", # optionales Addon für aufzurufende Funktion
@ -2047,6 +2010,34 @@ sub _detailViewOn {
return ($errstate,$state,$reread,$retry); return ($errstate,$state,$reread,$retry);
} }
################################################################
# Abruf Settings eines Consumers mit SUSyID 315
# (z.B. nach HTML 302 Weiterleitung)
################################################################
sub _getConsumerEnergySetting { ## no critic "not used"
my $paref = shift;
my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent
my $state = $paref->{state};
my $daref = $paref->{daref}; # Referenz zum Datenarray
my $oid = $paref->{oid}; # Consumer oid
my $addon = $paref->{addon}; # optionales AddOn - hier das managed Device
my ($reread,$retry,$errstate) = (0,0,0);
($errstate,$state) = __dispatchGet ({ name => $name,
ua => $ua,
call => 'https://www.sunnyportal.com/HoMan/Consumer/Semp/'.$oid,
tag => "consumerCurrentdata",
state => $state,
fnaref => [ qw( extractConsumerEnergySetting ) ],
addon => $addon,
daref => $daref
});
return ($errstate,$state,$reread,$retry);
}
################################################################ ################################################################
# Dispatcher GET # Dispatcher GET
################################################################ ################################################################
@ -2058,7 +2049,7 @@ sub __dispatchGet {
my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten my $tag = $paref->{tag}; # Kennzeichen der abzurufenen Daten
my $state = $paref->{state}; my $state = $paref->{state};
my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion my $addon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -2082,7 +2073,7 @@ sub __dispatchGet {
my @func = @$fnref; my @func = @$fnref;
no strict "refs"; ## no critic 'NoStrict' no strict "refs"; ## no critic 'NoStrict'
for my $fn (@func) { for my $fn (@func) {
&{$fn} ($hash,$daref,$data_cont,$fnaddon,$data); &{$fn} ($hash,$daref,$data_cont,$addon,$data);
} }
use strict "refs"; use strict "refs";
} }
@ -2103,7 +2094,7 @@ sub __dispatchPost {
my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion my $fnref = $paref->{fnaref}; # Referenz zu Array der aufzurufenden Funktion(en) zur Datenextraktion
my $fields = $paref->{fields}; # Referenz zum Hash der zu übertragenden PUSH Header my $fields = $paref->{fields}; # Referenz zum Hash der zu übertragenden PUSH Header
my $cont = $paref->{content}; # Content Daten für PUSH (String) my $cont = $paref->{content}; # Content Daten für PUSH (String)
my $fnaddon = $paref->{addon}; # optionales Addon für aufzurufende Funktion my $addon = $paref->{addon}; # optionales Addon für aufzurufende Funktion
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -2131,10 +2122,11 @@ sub __dispatchPost {
my $params = { my $params = {
hash => $hash, hash => $hash,
ua => $ua,
daref => $daref, daref => $daref,
data_cont => $data_cont, data_cont => $data_cont,
data => $data, data => $data,
fnaddon => $fnaddon, addon => $addon,
tag => $tag tag => $tag
}; };
@ -2334,9 +2326,11 @@ sub ___analyzeData { ## no critic 'complexity'
$njdat = encode("utf8", $ad->decoded_content); $njdat = encode("utf8", $ad->decoded_content);
Log3 ($name, 5, "$name - No JSON Data received:\n ".$njdat); Log3 ($name, 5, "$name - No JSON Data received:\n ".$njdat);
$errstate = 1 if($rescode != 302); # 302 -> HTTP-Antwort liefert zusätzlich eine URL im Header-Feld Location. Es soll eine zweite, ansonsten identische Anfrage an die in Location angegebene neue URL gestellt werden. if($rescode != 302) { # 302 -> HTTP-Antwort liefert zusätzlich eine URL im Header-Feld Location. Es soll eine zweite, ansonsten identische Anfrage an die in Location angegebene neue URL gestellt werden.
$errstate = 1;
$state = "ERROR - see logfile for further information"; $state = "ERROR - see logfile for further information";
} }
}
return ($reread,$retry,$errstate,$state); return ($reread,$retry,$errstate,$state);
} }
@ -2422,7 +2416,7 @@ sub ParseData {
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
my $ldlv = $stpl{liveData}{level}; my $ldlv = $stpl{liveData}{level};
my $cclv = $stpl{consumerCurrentdata}{level}; # my $cclv = $stpl{consumerCurrentdata}{level};
my $lddo = $subs{$name}{liveData}{doit}; my $lddo = $subs{$name}{liveData}{doit};
my $pv = ReadingsNum($name, "${ldlv}_PV" , 0); my $pv = ReadingsNum($name, "${ldlv}_PV" , 0);
@ -2438,11 +2432,11 @@ sub ParseData {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
if(!$errstate) { if(!$errstate) {
if($setp ne "none") { # if($setp ne "none") {
my ($d,$susyid,$op) = split(":",$setp); # my ($d,$susyid,$op) = split(":",$setp);
$op = ($op eq "auto") ? "off (automatic)" : $op; # $op = ($op eq "auto") ? "off (automatic)" : $op;
readingsBulkUpdate($hash, "${cclv}_${d}_Switch", $op); # readingsBulkUpdate($hash, "${cclv}_${d}_Switch", $op) if($susyid == 191);
} # }
readingsBulkUpdate($hash, "lastCycleTime", $ctime ) if($ctime > 0); readingsBulkUpdate($hash, "lastCycleTime", $ctime ) if($ctime > 0);
readingsBulkUpdate($hash, "summary", $sum." W") if($subs{$name}{liveData}{doit}); readingsBulkUpdate($hash, "summary", $sum." W") if($subs{$name}{liveData}{doit});
readingsBulkUpdate($hash, "lastSuccessTime", $ts ); readingsBulkUpdate($hash, "lastSuccessTime", $ts );
@ -2796,7 +2790,7 @@ sub extractStatisticData {
my $daref = $paref->{daref}; my $daref = $paref->{daref};
my $data_cont = $paref->{data_cont}; # empfangene Daten decoded Content my $data_cont = $paref->{data_cont}; # empfangene Daten decoded Content
my $data = $paref->{data}; # empfangene Rohdaten my $data = $paref->{data}; # empfangene Rohdaten
my $period = $paref->{fnaddon}; my $period = $paref->{addon};
my $tag = $paref->{tag}; my $tag = $paref->{tag};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -2833,7 +2827,9 @@ sub extractPlantMasterData {
my $forecast = shift; my $forecast = shift;
my $addon = shift; my $addon = shift;
my $data = shift; # gelieferte Rohdaten my $data = shift; # gelieferte Rohdaten
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my ($amount,$unit); my ($amount,$unit);
Log3 ($name, 4, "$name - ##### extracting plant master data #### "); Log3 ($name, 4, "$name - ##### extracting plant master data #### ");
@ -2928,6 +2924,7 @@ sub extractConsumerPlanData {
my $hash = shift; my $hash = shift;
my $daref = shift; my $daref = shift;
my $forecast = shift; my $forecast = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %consumers; my %consumers;
my ($key,$val); my ($key,$val);
@ -3011,6 +3008,7 @@ sub extractConsumerMasterdata {
my $hash = shift; my $hash = shift;
my $daref = shift; my $daref = shift;
my $clivedata = shift; my $clivedata = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %consumers; my %consumers;
my %hcon; my %hcon;
@ -3063,6 +3061,7 @@ sub extractConsumerCurrentdata {
my $hash = shift; my $hash = shift;
my $daref = shift; my $daref = shift;
my $clivedata = shift; my $clivedata = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %consumers; my %consumers;
my ($i,$res); my ($i,$res);
@ -3136,6 +3135,7 @@ sub extractConsumerHistData { #
my $daref = shift; my $daref = shift;
my $chdata = shift; my $chdata = shift;
my $tf = shift; my $tf = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %consumers; my %consumers;
my ($i,$gcr,$gct,$pcr,$pct,$tct,$bcr,$bct); my ($i,$gcr,$gct,$pcr,$pct,$tct,$bcr,$bct);
@ -3206,7 +3206,7 @@ sub extractSwitchConsumerData {
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $data_cont = $paref->{data_cont}; # Daten decoded Content my $data_cont = $paref->{data_cont}; # Daten decoded Content
my $data = $paref->{data}; # empfangene Rohdaten my $data = $paref->{data}; # empfangene Rohdaten
my $addon = $paref->{fnaddon}; # ein optionales AddOn my $addon = $paref->{addon}; # ein optionales AddOn
my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -3221,6 +3221,10 @@ sub extractSwitchConsumerData {
$state = "ok - switched consumer $d to $op"; $state = "ok - switched consumer $d to $op";
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "GETTER:all" ], 1); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "GETTER:all" ], 1);
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "SETTER:none"], 1); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "SETTER:none"], 1);
my $cclv = $stpl{consumerCurrentdata}{level};
$op = ($op eq "auto") ? "off (automatic)" : $op;
push @$daref, "${cclv}_${d}_Switch:$op";
} }
else { else {
$state = "ERROR - couldn't switch consumer $d to $op"; $state = "ERROR - couldn't switch consumer $d to $op";
@ -3233,32 +3237,49 @@ return $state;
# Auswertung Ergebnis aus Manage Consumer # Auswertung Ergebnis aus Manage Consumer
# By Energy # By Energy
################################################################ ################################################################
sub extractConsumerByEnergyData { sub extractManageConsumerByEnergy {
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $ua = $paref->{ua}; # LWP Useragent
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $data_cont = $paref->{data_cont}; # Daten decoded Content my $data_cont = $paref->{data_cont}; # Daten decoded Content
my $data = $paref->{data}; # empfangene Rohdaten my $data = $paref->{data}; # empfangene Rohdaten
my $addon = $paref->{fnaddon}; # ein optionales AddOn my $addon = $paref->{addon}; # ein optionales AddOn
my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my ($errstate,$reread,$retry) = (0,0,0);
Log3 ($name, 4, "$name - extracting manage Consumer by energy result "); Log3 ($name, 4, "$name - extracting manage Consumer by energy result ");
my $rescode = $data->code; # HTML Code der Antwort (sollte 302 sein bei Erfolg) my $rescode = $data->code; # HTML Code der Antwort (sollte 302 sein bei Erfolg)
my $location = $data->header('Location');
my ($d,$susyid,$op) = split(":",$addon); # $op -> eingestellter Gridconsomption Schwellenwert my ($d,$susyid,$op) = split(":",$addon); # $op -> eingestellter Gridconsomption Schwellenwert
my $pvlog = 100-$op; my $pvlog = 100-$op;
my $state; my $state;
if($rescode == 302) { if($rescode == 302) {
my $location = $data->header('Location');
$state = qq{ok - Consumer "$d" set to condition: switch on if GridConsumption=$op% (PV=$pvlog%) is fulfilled}; $state = qq{ok - Consumer "$d" set to condition: switch on if GridConsumption=$op% (PV=$pvlog%) is fulfilled};
Log3 ($name, 3, qq{$name - $state}); Log3 ($name, 3, qq{$name - $state});
Log3 ($name, 3, qq{$name - GET "$location" to read the new values are set }); Log3 ($name, 3, qq{$name - next step: GET "$location" to read the new values are set });
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "GETTER:all" ], 1); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "GETTER:all" ], 1);
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "SETTER:none"], 1); BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "SETTER:none"], 1);
for my $key (keys %{$hash->{HELPER}{CONSUMER}}) {
my $h = $hash->{HELPER}{CONSUMER}{$key}{DeviceName};
if($h && $h eq $d) {
$paref->{oid} = $hash->{HELPER}{CONSUMER}{$key}{ConsumerOid};
}
}
$paref->{name} = $name;
$paref->{state} = $state;
$paref->{addon} = $d; # das gemanagte Device in addon mitgeben
($errstate,$state,$reread,$retry) = _getConsumerEnergySetting ($paref);
} }
else { else {
$state = qq{ERROR - couldn't set Consumer "$d" set to condition: switch on if GridConsumption=$op% (PV=$pvlog%)}; $state = qq{ERROR - couldn't set Consumer "$d" set to condition: switch on if GridConsumption=$op% (PV=$pvlog%)};
@ -3267,6 +3288,34 @@ sub extractConsumerByEnergyData {
return $state; return $state;
} }
################################################################
# Abruf der aktuell eingestellten Energy Management Settings
# von Verbrauchern des Typs 315 (z.B. SMA EV Charger)
################################################################
sub extractConsumerEnergySetting {
my $hash = shift;
my $daref = shift;
my $data_cont = shift; # gelieferter data content
my $addon = shift;
my $data = shift; # gelieferte Rohdaten
my $name = $hash->{NAME};
my ($errstate,$reread,$retry) = (0,0,0);
Log3 ($name, 4, "$name - extracting current Consumer energy settings ");
my $d = $addon;
my $cclv = $stpl{consumerCurrentdata}{level};
my ($gcval) = $data_cont =~ /var\sgridConsumptionValue\s=\s0\.(\d{2});/x // "undefined";
my ($pvval) = $data_cont =~ /var\spvValue\s=\s0\.(\d{2});/x // "undefined";
push @$daref, "${cclv}_${d}_SwitchCondition:GridConsumption=$gcval% PV=$pvval%";
return;
}
################################################################ ################################################################
# Auswertung Daten aus Hilfsroutinen # Auswertung Daten aus Hilfsroutinen
################################################################ ################################################################
@ -3276,7 +3325,7 @@ sub extractHelperData {
my $daref = $paref->{daref}; # Referenz zum Datenarray my $daref = $paref->{daref}; # Referenz zum Datenarray
my $data_cont = $paref->{data_cont}; # Daten decoded Content my $data_cont = $paref->{data_cont}; # Daten decoded Content
my $data = $paref->{data}; # empfangene Rohdaten my $data = $paref->{data}; # empfangene Rohdaten
my $addon = $paref->{fnaddon}; # ein optionales AddOn my $addon = $paref->{addon}; # ein optionales AddOn
my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine my $tag = $paref->{tag}; # Kennzeichen der abgerufenen Daten/ der Abrufroutine
my $name = $hash->{NAME}; my $name = $hash->{NAME};