mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
76_SMAPortal: contrib 2.8.0
git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@22081 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
d9fa75af3e
commit
54b11394fb
@ -43,7 +43,7 @@ use POSIX;
|
|||||||
eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; ## no critic 'eval'
|
eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; ## no critic 'eval'
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
use Blocking;
|
use Blocking;
|
||||||
use Time::HiRes qw(gettimeofday time);
|
use Time::HiRes qw(gettimeofday time sleep);
|
||||||
use Time::Local;
|
use Time::Local;
|
||||||
use LWP::UserAgent;
|
use LWP::UserAgent;
|
||||||
use HTTP::Cookies;
|
use HTTP::Cookies;
|
||||||
@ -134,7 +134,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
"2.8.0" => "30.05.2020 refactoring process logic, attribute cookielifetime & getDataRetries deleted, command delCookieFile deleted ".
|
"2.8.0" => "31.05.2020 refactoring process logic, attribute cookielifetime & getDataRetries deleted, command delCookieFile deleted ".
|
||||||
"new attribute maxCallCycle ",
|
"new attribute maxCallCycle ",
|
||||||
"2.7.2" => "28.05.2020 delete cookie file if threshold of read retries reached ",
|
"2.7.2" => "28.05.2020 delete cookie file if threshold of read retries reached ",
|
||||||
"2.7.1" => "28.05.2020 change cookie default location to ./log/<name>_cookie.txt ",
|
"2.7.1" => "28.05.2020 change cookie default location to ./log/<name>_cookie.txt ",
|
||||||
@ -185,7 +185,10 @@ my %vNotesIntern = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
# Voreinstellungen
|
# Voreinstellungen
|
||||||
my $maxretries = 4; # max. Anzahl Wiederholunegn in einem Abtuf-Cycle
|
my $maxretries = 4; # max. Anzahl Wiederholunegn in einem Abruf-Zyklus
|
||||||
|
my $sleepretry = 0.5; # Sleep zwischen Data Call Retries (ohne Threshold Überschreitung)
|
||||||
|
my $sleepexc = 2; # Sleep vor neuem Datencall nach Überschreitung Threshold (Data Calls mit gleichem Cookie)
|
||||||
|
my $maxcycles = 5; # max. Anzahl Datenabruf Zyklen
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
# SMAPortal Initialize
|
# SMAPortal Initialize
|
||||||
@ -616,10 +619,11 @@ return;
|
|||||||
# Hauptschleife BlockingCall
|
# Hauptschleife BlockingCall
|
||||||
# $hash->{HELPER}{GETTER} -> Flag für get Informationen
|
# $hash->{HELPER}{GETTER} -> Flag für get Informationen
|
||||||
# $hash->{HELPER}{SETTER} -> Parameter für set-Befehl
|
# $hash->{HELPER}{SETTER} -> Parameter für set-Befehl
|
||||||
# $nc = 1 wenn ein neuer Abrufcyclus gestartet werden soll
|
# $nc = 1 wenn Cycle Zähler nicht zurückgesetzt werden soll
|
||||||
|
# $nr = 1 wenn Retry Zähler nicht zurückgesetzt werden soll
|
||||||
################################################################
|
################################################################
|
||||||
sub CallInfo {
|
sub CallInfo {
|
||||||
my ($hash,$nc) = @_;
|
my ($hash,$nc,$nr) = @_;
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $timeout = AttrVal($name, "timeout", 30);
|
my $timeout = AttrVal($name, "timeout", 30);
|
||||||
my $interval = AttrVal($name, "interval", 300);
|
my $interval = AttrVal($name, "interval", 300);
|
||||||
@ -652,19 +656,22 @@ sub CallInfo {
|
|||||||
my $getp = $hash->{HELPER}{GETTER};
|
my $getp = $hash->{HELPER}{GETTER};
|
||||||
my $setp = $hash->{HELPER}{SETTER};
|
my $setp = $hash->{HELPER}{SETTER};
|
||||||
|
|
||||||
Log3 ($name, 4, "$name - ################################################################");
|
if(!$nc && !$nr) {
|
||||||
Log3 ($name, 4, "$name - ### start of set/get data from SMA Sunny Portal ###");
|
Log3 ($name, 3, "$name - ################################################################");
|
||||||
Log3 ($name, 4, "$name - ################################################################");
|
Log3 ($name, 3, "$name - ### start new set/get data from SMA Sunny Portal ###");
|
||||||
|
Log3 ($name, 3, "$name - ################################################################");
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{HELPER}{ACTCYCLE} = 1 if(!$nc);
|
||||||
|
$hash->{HELPER}{RETRIES} = 1 if(!$nr);
|
||||||
|
|
||||||
$hash->{HELPER}{ACTCYCLE} = 0 if(!$nc);
|
|
||||||
my $ac = $hash->{HELPER}{ACTCYCLE};
|
my $ac = $hash->{HELPER}{ACTCYCLE};
|
||||||
my $maxac = AttrVal($name, "maxCallCycle", 5);
|
my $maxac = AttrVal($name, "maxCallCycle", $maxcycles);
|
||||||
|
|
||||||
Log3 ($name, 3, "$name - Running data cycle: $ac of maximum $maxac");
|
Log3 ($name, 3, "$name - Running data cycle: $ac of maximum $maxac");
|
||||||
|
|
||||||
readingsSingleUpdate($hash, "state", "running - call cycle $ac", 1);
|
readingsSingleUpdate($hash, "state", "running - call cycle $ac", 1);
|
||||||
|
|
||||||
$hash->{HELPER}{RETRIES} = $maxretries;
|
|
||||||
$hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetSetData", "$name|$getp|$setp", "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash);
|
$hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetSetData", "$name|$getp|$setp", "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash);
|
||||||
$hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057
|
$hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057
|
||||||
|
|
||||||
@ -690,6 +697,7 @@ sub GetSetData { ## no cri
|
|||||||
my ($ccyeardata_content) = ("");
|
my ($ccyeardata_content) = ("");
|
||||||
my $state = "ok";
|
my $state = "ok";
|
||||||
my ($reread,$retry) = (0,0);
|
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,$ccdaydata_content,$ccmonthdata_content) = ("","","","","");
|
||||||
my ($livedata_content,$d,$op);
|
my ($livedata_content,$d,$op);
|
||||||
|
|
||||||
@ -771,7 +779,7 @@ sub GetSetData { ## no cri
|
|||||||
handleCounter ($name, "dailyIssueCookieCounter"); # Cookie Ausstellungszähler setzen
|
handleCounter ($name, "dailyIssueCookieCounter"); # Cookie Ausstellungszähler setzen
|
||||||
|
|
||||||
$livedata_content = '{"Login-Status":"successful", "InfoMessages":["login to SMA-Portal successful."]}';
|
$livedata_content = '{"Login-Status":"successful", "InfoMessages":["login to SMA-Portal successful."]}';
|
||||||
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "NULL", (gettimeofday())[0], "NULL"], 0);
|
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "NULL", (gettimeofday())[0], "NULL", "NULL"], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $shmp = $ua->get('https://www.sunnyportal.com/FixedPages/HoManLive.aspx');
|
my $shmp = $ua->get('https://www.sunnyportal.com/FixedPages/HoManLive.aspx');
|
||||||
@ -784,25 +792,31 @@ sub GetSetData { ## no cri
|
|||||||
goto &GetSetData if($reread);
|
goto &GetSetData if($reread);
|
||||||
|
|
||||||
# Wiederholung Datenabruf innerhalb eines Cycle
|
# Wiederholung Datenabruf innerhalb eines Cycle
|
||||||
my $ac = $hash->{HELPER}{ACTCYCLE};
|
|
||||||
my $maxcc = AttrVal($name, "maxCallCycle", 5);
|
|
||||||
my $retc = $hash->{HELPER}{RETRIES};
|
my $retc = $hash->{HELPER}{RETRIES};
|
||||||
|
|
||||||
if($getp ne "none" && $retry && $retc >= 0 && $ac <= $maxcc) { # Livedaten konnten nicht gelesen werden, neuer Versuch zeitverzögert
|
if($setp eq "none" && $retry && $retc < $maxretries) { # neuer Retry im gleichen Zyklus (nicht wenn Verbraucher schalten)
|
||||||
my $act = $maxretries - $retc; # Index aktueller Wiederholungsversuch
|
$hash->{HELPER}{RETRIES}++;
|
||||||
|
if($maxretries - $retc == 1) { # Schwellenwert erreicht ($max-1 Leseversuche) -> Cookie File löschen
|
||||||
$hash->{HELPER}{RETRIES} -= 1;
|
Log3 ($name, 3, qq{$name - Threshold reached, delete cookie and retry ...});
|
||||||
|
sleep $sleepexc; # Threshold exceed -> Retry mit Cookie löschen
|
||||||
if($maxretries - $act == 0) { # Schwellenwert erreicht ($max-1 Leseversuche) -> Cookie File löschen
|
$exceed = 1;
|
||||||
Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...});
|
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "NULL", "NULL", "NULL", $hash->{HELPER}{RETRIES}], 1);
|
||||||
sleep 3; # Verzögerung next cycle
|
return "$name|$exceed|$newcycle|$login_state|$getp|$setp";
|
||||||
return "$name|1|$login_state|$getp|$setp"; # threshold exceed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# sleep 3; # Perl Sleep -> nur im BlockingCall !
|
sleep $sleepretry;
|
||||||
goto &GetSetData;
|
goto &GetSetData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Wiederholung Datenabruf in einem neuen Cycle
|
||||||
|
my $ac = $hash->{HELPER}{ACTCYCLE};
|
||||||
|
my $maxcc = AttrVal($name, "maxCallCycle", $maxcycles);
|
||||||
|
if($setp eq "none" && $retry && $ac < $maxcc) { # neuer Zyklus (nicht wenn Verbraucher schalten)
|
||||||
|
Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...});
|
||||||
|
$newcycle = 1;
|
||||||
|
return "$name|$exceed|$newcycle|$login_state|$getp|$setp";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
### Verbraucher schalten
|
### Verbraucher schalten
|
||||||
#######################################
|
#######################################
|
||||||
@ -828,7 +842,7 @@ sub GetSetData { ## no cri
|
|||||||
Log3 ($name, 3, "$name - Set \"$d $op\" result: ".$res);
|
Log3 ($name, 3, "$name - Set \"$d $op\" result: ".$res);
|
||||||
if($res eq "true") {
|
if($res eq "true") {
|
||||||
$state = "ok - switched consumer $d to $op";
|
$state = "ok - switched consumer $d to $op";
|
||||||
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "all", "none", "NULL", "NULL"], 0);
|
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "all", "none", "NULL", "NULL", "NULL"], 0);
|
||||||
} else {
|
} else {
|
||||||
$state = "Error - couldn't switched consumer $d to $op";
|
$state = "Error - couldn't switched consumer $d to $op";
|
||||||
}
|
}
|
||||||
@ -944,7 +958,7 @@ sub GetSetData { ## no cri
|
|||||||
$cm = encode_base64($ccmonthdata_content,"") if($ccmonthdata_content);
|
$cm = encode_base64($ccmonthdata_content,"") if($ccmonthdata_content);
|
||||||
$cy = encode_base64($ccyeardata_content,"") if($ccyeardata_content);
|
$cy = encode_base64($ccyeardata_content,"") if($ccyeardata_content);
|
||||||
|
|
||||||
return "$name|0|$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";
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
@ -957,34 +971,43 @@ sub ParseData { ## no critic
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $timeout = AttrVal($name, "timeout", 30);
|
my $timeout = AttrVal($name, "timeout", 30);
|
||||||
|
|
||||||
my ($login_state,$retry,$getp,$setp,$fc,$wc,$cl,$cd,$cm,$cy,$lc,$state,$exceed);
|
my ($login_state,$newcycle,$getp,$setp,$fc,$wc,$cl,$cd,$cm,$cy,$lc,$state,$exceed);
|
||||||
|
|
||||||
$exceed = $a[1];
|
$exceed = $a[1];
|
||||||
$login_state = $a[2];
|
$newcycle = $a[2];
|
||||||
$getp = $a[3];
|
$login_state = $a[3];
|
||||||
$setp = $a[4];
|
$getp = $a[4];
|
||||||
|
$setp = $a[5];
|
||||||
|
|
||||||
my $ac = $hash->{HELPER}{ACTCYCLE};
|
my $ac = $hash->{HELPER}{ACTCYCLE};
|
||||||
my $maxac = AttrVal($name, "maxCallCycle", 5);
|
my $maxac = AttrVal($name, "maxCallCycle", $maxcycles);
|
||||||
|
|
||||||
if($exceed && $ac <= $maxac) {
|
if($exceed) {
|
||||||
delete($hash->{HELPER}{RUNNING_PID});
|
delete($hash->{HELPER}{RUNNING_PID});
|
||||||
delcookiefile ($hash);
|
delcookiefile ($hash);
|
||||||
$hash->{HELPER}{GETTER} = $getp;
|
$hash->{HELPER}{GETTER} = $getp;
|
||||||
$hash->{HELPER}{SETTER} = $setp;
|
$hash->{HELPER}{SETTER} = $setp;
|
||||||
$hash->{HELPER}{ACTCYCLE}++;
|
CallInfo($hash,1,1); # neuer Versuch (nach Threshold exceed) im gleichen Cycle mit gelöschtem Cookie
|
||||||
CallInfo($hash,1); # neuer Abrufcycle
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = decode_base64($a[5]);
|
if($newcycle && $ac < $maxac) {
|
||||||
$lc = decode_base64($a[6]);
|
delete($hash->{HELPER}{RUNNING_PID});
|
||||||
$fc = decode_base64($a[7]) if($a[7]);
|
$hash->{HELPER}{GETTER} = $getp;
|
||||||
$wc = decode_base64($a[8]) if($a[8]);
|
$hash->{HELPER}{SETTER} = $setp;
|
||||||
$cl = decode_base64($a[9]) if($a[9]);
|
$hash->{HELPER}{ACTCYCLE}++;
|
||||||
$cd = decode_base64($a[10]) if($a[10]);
|
CallInfo($hash,1,0); # neuer Abrufcycle
|
||||||
$cm = decode_base64($a[11]) if($a[11]);
|
return;
|
||||||
$cy = decode_base64($a[12]) if($a[12]);
|
}
|
||||||
|
|
||||||
|
$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 ($livedata_content,$forecast_content,$weatherdata_content,$consumerlivedata_content);
|
||||||
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content);
|
my ($ccdaydata_content,$ccmonthdata_content,$ccyeardata_content);
|
||||||
@ -1771,33 +1794,37 @@ sub handleCounter {
|
|||||||
}
|
}
|
||||||
$count++;
|
$count++;
|
||||||
$cstring = "$rd:$day:$count";
|
$cstring = "$rd:$day:$count";
|
||||||
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "NULL", "NULL", $cstring], 1);
|
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "NULL", "NULL", "NULL", $cstring, "NULL"], 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Werte aus BlockingCall heraus setzen
|
# Werte aus BlockingCall heraus setzen
|
||||||
|
# Erwartete Liste:
|
||||||
|
# @setl = $name,$getp,$setp,$logintime,$setread,$retries
|
||||||
################################################################
|
################################################################
|
||||||
sub setFromBlocking {
|
sub setFromBlocking {
|
||||||
my ($name,$getp,$setp,$logintime,$counter) = @_;
|
my (@setl) = @_;
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$setl[0]};
|
||||||
|
|
||||||
$getp = $getp // "NULL";
|
my $getp = $setl[1] // "NULL";
|
||||||
$setp = $setp // "NULL";
|
my $setp = $setl[2] // "NULL";
|
||||||
$logintime = $logintime // "NULL";
|
my $logintime = $setl[3] // "NULL";
|
||||||
$counter = $counter // "NULL";
|
my $setread = $setl[4] // "NULL";
|
||||||
|
my $retries = $setl[5] // "NULL";
|
||||||
|
|
||||||
$hash->{HELPER}{GETTER} = $getp if($getp ne "NULL");
|
$hash->{HELPER}{GETTER} = $getp if($getp ne "NULL");
|
||||||
$hash->{HELPER}{SETTER} = $setp if($setp ne "NULL");
|
$hash->{HELPER}{SETTER} = $setp if($setp ne "NULL");
|
||||||
|
$hash->{HELPER}{RETRIES} = $retries if($retries ne "NULL");
|
||||||
|
|
||||||
if($logintime ne "NULL") {
|
if($logintime ne "NULL") {
|
||||||
$hash->{HELPER}{oldlogintime} = $logintime;
|
$hash->{HELPER}{oldlogintime} = $logintime;
|
||||||
readingsSingleUpdate($hash, "L1_Login-Status", "successful", 1);
|
readingsSingleUpdate($hash, "L1_Login-Status", "successful", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($counter ne "NULL") {
|
if($setread ne "NULL") {
|
||||||
my @cparts = split ":", $counter, 2;
|
my @cparts = split ":", $setread, 2;
|
||||||
readingsSingleUpdate($hash, $cparts[0], $cparts[1], 1);
|
readingsSingleUpdate($hash, $cparts[0], $cparts[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1812,7 +1839,7 @@ sub analyzeData { ## no
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my ($reread,$retry) = (0,0);
|
my ($reread,$retry) = (0,0);
|
||||||
|
|
||||||
my $act = $maxretries - $hash->{HELPER}{RETRIES}; # Index aktueller Wiederholungsversuch
|
my $act = $hash->{HELPER}{RETRIES}; # Index aktueller Wiederholungsversuch
|
||||||
my $attstr = "Attempts read data again ... ($act of $maxretries)";
|
my $attstr = "Attempts read data again ... ($act of $maxretries)";
|
||||||
|
|
||||||
my $livedata_content = decode_json($lc);
|
my $livedata_content = decode_json($lc);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user