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

76_SMAPortal: imptove cookie/login management

git-svn-id: https://svn.fhem.de/fhem/trunk@22276 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2020-06-26 19:39:47 +00:00
parent cbbf89e124
commit 1b5fe39087
2 changed files with 66 additions and 38 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
- change: 76_SMAPortal: imptove cookie/login management
- feature: 49_SSCam / 49_SSCamSTRM: new capability operate PTZ Zoom cameras
- changed: 76_SMAPortal: get plantOid from cookie if not in JSON
- bugfix: 70_ZoneMinder: fix afterInitialized (thx GeberNehmer)

View File

@ -136,6 +136,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
"3.1.2" => "25.06.2020 don't delete cookie after every data retrieval, change login management ",
"3.1.1" => "24.06.2020 change german Error regex, get plantOid from cookie if not in JSON ",
"3.1.0" => "20.06.2020 language of SMA Portal messages depend on global language attribute, avoid order problems by ".
"executing retrieve master data firstly every time",
@ -200,8 +201,8 @@ my %vNotesIntern = (
);
# Voreinstellungen
my $maxretries = 6; # max. Anzahl Wiederholungen in einem Abruf-Zyklus
my $thold = int($maxretries/2); # Schwellenwert nicht erfolgreicher Leseversuche in einem Zyklus mit dem gleichen Cookie
my $maxretries = 8; # max. Anzahl Wiederholungen in einem Abruf-Zyklus
my $thold = int($maxretries/2); # Schwellenwert nicht erfolgreicher Leseversuche in einem Zyklus mit dem gleichen Cookie, Standard: int($maxretries/2)
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 $defmaxcycles = 19; # Standard max. Anzahl Datenabrufzyklen abgeleitet von Interval 120 (wird bei Automatic berechnet)
@ -381,6 +382,7 @@ sub Set { ## no critic 'complexity'
($success) = setcredentials($hash,$prop,$prop1);
if($success) {
delcookiefile ($hash);
CallInfo($hash);
return "Username and Password saved successfully";
} else {
@ -658,7 +660,8 @@ sub Attr {
$val = ($do == 1 ? "disabled" : "initialized");
if($do) {
deleteData($hash);
deleteData ($hash);
delcookiefile ($hash);
delete $hash->{MODE};
RemoveInternalTimer($hash);
} else {
@ -812,16 +815,16 @@ return ($interval,$maxcycles,$timeout,$ctime);
################################################################
sub GetSetData { ## no critic 'complexity'
my ($string) = @_;
my ($name,$getp,$setp) = split("\\|",$string);
my $hash = $defs{$name};
my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt");
my $v5d = AttrVal($name, "verbose5Data", "none");
my $verbose = AttrVal($name, "verbose", 3);
my $lang = AttrVal("global", "language", "EN");
my $state = "ok";
my ($st,$lc) = ("","");
my @da = ();
my ($name,$getp,$setp) = split("\\|",$string);
my $hash = $defs{$name};
my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)");
my $cookieLocation = AttrVal($name, "cookieLocation", "./log/".$name."_cookie.txt");
my $v5d = AttrVal($name, "verbose5Data", "none");
my $verbose = AttrVal($name, "verbose", 3);
my $lang = AttrVal("global", "language", "EN");
my $state = "ok";
my ($st,$lc) = ("","");
my @da = ();
my ($errstate,$reread,$retry,$exceed,$newcycle) = (0,0,0,0,0);
@ -866,7 +869,7 @@ sub GetSetData { ## no cri
### Login
##############
my $paref = [ $name, $ua, $state, $errstate ];
($state, $errstate) = _checkLogin ($paref);
($state, $errstate) = _doLogin ($paref);
if($errstate) {
$st = encode_base64 ( $state,"");
@ -944,7 +947,7 @@ sub GetSetData { ## no cri
goto &GetSetData if($reread);
# Wiederholung Datenabruf innerhalb eines Cycle
my $retc = $hash->{HELPER}{RETRIES}; # aktuelle Retry-Zähler
my $retc = $hash->{HELPER}{RETRIES}; # aktuelle Retry-Zähler
if($retry && $retc < $maxretries) { # neuer Retry im gleichen Zyklus (nicht wenn Verbraucher schalten)
$hash->{HELPER}{RETRIES}++;
@ -964,7 +967,7 @@ sub GetSetData { ## no cri
my $ac = $hash->{HELPER}{ACTCYCLE};
my $maxcycles = (controlParams $name)[1];
if($retry && $ac < $maxcycles) { # neuer Zyklus (nicht wenn Verbraucher schalten)
Log3 ($name, 3, qq{$name - Maximum retries reached, delete cookie and start new cycle ...});
Log3 ($name, 3, qq{$name - Maximum retries reached, start new data get cycle ...});
$newcycle = 1;
return "$name|$exceed|$newcycle|$errstate|$getp|$setp";
}
@ -976,6 +979,7 @@ sub GetSetData { ## no cri
if(@da) {
$lc = join "###", @da;
$lc = encode_base64 ( $lc, "");
Log3 ($name, 3, "$name - data retrieved successfully.");
}
return "$name|$exceed|$newcycle|$errstate|$getp|$setp|$st|$lc";
@ -984,7 +988,7 @@ return "$name|$exceed|$newcycle|$errstate|$getp|$setp|$st|$lc";
################################################################
# Login Status checken und ggf. einloggen
################################################################
sub _checkLogin {
sub _doLogin {
my $paref = shift;
my $name = $paref->[0];
my $ua = $paref->[1];
@ -994,30 +998,31 @@ sub _checkLogin {
my $hash = $defs{$name};
my $v5d = AttrVal($name, "verbose5Data", "none");
my $verbose = AttrVal($name, "verbose", 3);
my $loginp = $ua->post('https://www.sunnyportal.com/Templates/Start.aspx');
my $retcode = $loginp->code;
my $location = $loginp->header('Location') // "";
if($verbose == 5 && $v5d =~ /loginData/) {
$ua->add_handler( request_send => sub { shift->dump; return } ); # for debugging
$ua->add_handler( response_done => sub { shift->dump; return } );
}
my ($success, $username, $password) = getcredentials($hash,0); # gespeicherte Credentials abrufen
my $loginp = $ua->post('https://www.sunnyportal.com/Templates/Start.aspx');
my $retcode = $loginp->code;
my $location = $loginp->header('Location') // "";
my $cookie = $loginp->header('Set-Cookie') // "";
if ($loginp->is_success) {
if($v5d =~ /loginData/) {
Log3 ($name, 5, "$name - Status Login Page: ".$loginp->status_line);
Log3 ($name, 5, "$name - Header Location: ".$location);
Log3 ($name, 5, "$name - Header Location: ". $location);
Log3 ($name, 5, "$name - Header Set-Cookie: ".$cookie);
}
$retcode = $loginp->code;
$location = $loginp->header('Location') // "";
if($location ne "/FixedPages/HoManLive.aspx" || $retcode ne "302") { # keine aktive Session -> neuer Login
if(!__isLoggedIn ($name,$username,$loginp)) { # keine aktive Session -> neuer Login
Log3 ($name, 4, "$name - User not logged in. Try login with credentials ...");
# Credentials abrufen
my ($success, $username, $password) = getcredentials($hash,0);
if(!$success) {
Log3($name, 1, qq{$name - Credentials couldn't be retrieved successfully - make sure you've set it with "set $name credentials <username> <password>"});
@ -1044,29 +1049,31 @@ sub _checkLogin {
my ($logname) = $sc =~ /SunnyPortalLoginInfo=Username=(.*?)&/sx;
Log3 ($name, 5, "$name - Header Set-Cookie: ".$sc) if($v5d =~ /loginData/);
if($logname && $logname eq $username) { # Login erfolgeich(Landing Pages können im Portal eingestellt werden!)
Log3 ($name, 3, "$name - Login into SMA-Portal successfully done with user: $logname");
if(__isLoggedIn ($name,$username,$loginp)) { # Login erfolgeich(Landing Pages können im Portal eingestellt werden!)
handleCounter ($name, "dailyIssueCookieCounter"); # Cookie Ausstellungszähler setzen
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "loginState:successful", "oldlogintime:".(gettimeofday())[0] ], 1);
$errstate = 0;
} else {
Log3 ($name, 2, "$name - ERROR - Login into SMA-Portal failed !");
$state = "login failed - check user and password";
$state = "login failed";
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "loginState:failed", "NULL" ], 1);
$errstate = 1;
}
}
}
} elsif($loginp->is_redirect) {
} elsif ($loginp->is_redirect) {
$retcode = $loginp->code;
$location = $loginp->header('Location') // "";
Log3 ($name, 3, "$name - User is already logged in.");
if($v5d =~ /loginData/) {
Log3 ($name, 5, "$name - Redirect return code: ".$retcode);
Log3 ($name, 5, "$name - Redirect return code: ". $retcode );
Log3 ($name, 5, "$name - Redirect Header Location: ".$location);
}
BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "loginState:successful", "NULL" ], 1);
$errstate = 0;
} else {
@ -1082,15 +1089,34 @@ sub _checkLogin {
return ($state, $errstate);
}
################################################################
# Login Status testen
################################################################
sub __isLoggedIn {
my $name = shift;
my $username = shift;
my $loginp = shift;
my $sc = $loginp->header('Set-Cookie') // "";
my ($logname) = $sc =~ /SunnyPortalLoginInfo=Username=(.*?)&/sx;
if($logname && $logname eq $username) {
Log3 ($name, 3, "$name - Login into SMA-Portal successfully done with user: $logname");
return 1;
}
return 0;
}
################################################################
# Abruf Live Daten
################################################################
sub _getLiveData { ## 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 $paref = shift;
my $name = $paref->{name};
my $ua = $paref->{ua}; # LWP Useragent
my $state = $paref->{state};
my $daref = $paref->{daref}; # Referenz zum Datenarray
my ($reread,$retry,$errstate) = (0,0,0);
@ -1761,6 +1787,7 @@ sub ParseData { ## no critic
if($newcycle && $ac < $maxcycles) {
delete($hash->{HELPER}{RUNNING_PID});
delcookiefile ($hash);
$hash->{HELPER}{GETTER} = $getp;
$hash->{HELPER}{SETTER} = $setp;
$hash->{HELPER}{ACTCYCLE}++;
@ -1859,7 +1886,7 @@ sub finalCleanup {
$hash->{HELPER}{GETTER} = "all";
$hash->{HELPER}{SETTER} = "none";
delcookiefile ($hash);
#delcookiefile ($hash);
return;
}