add refresh token support

add refresh token after expired

[Ticket: #6]
This commit is contained in:
Marko Oldenburg 2022-01-29 05:23:18 +01:00
parent 55ce39b8d3
commit c2b4bd2ffc
3 changed files with 68 additions and 55 deletions

View File

@ -196,7 +196,7 @@ sub Initialize {
], ],
"release_status": "stable", "release_status": "stable",
"license": "GPL_2", "license": "GPL_2",
"version": "v2.0.1", "version": "v2.0.2",
"author": [ "author": [
"Marko Oldenburg <fhemdevelopment@cooltux.net>" "Marko Oldenburg <fhemdevelopment@cooltux.net>"
], ],

View File

@ -1,2 +1,2 @@
UPD 2022-01-09_15:44:54 6874 FHEM/46_TeslaPowerwall2AC.pm UPD 2022-01-29_04:24:06 6874 FHEM/46_TeslaPowerwall2AC.pm
UPD 2022-01-09_15:59:59 27461 lib/FHEM/Devices/Tesla/Powerwall.pm UPD 2022-01-29_05:20:11 27899 lib/FHEM/Devices/Tesla/Powerwall.pm

View File

@ -161,17 +161,17 @@ sub Define {
my $name = $aArg->[0]; my $name = $aArg->[0];
my $host = $aArg->[2]; my $host = $aArg->[2];
$hash->{HOST} = $host; $hash->{HOST} = $host;
$hash->{INTERVAL} = 300; $hash->{INTERVAL} = 300;
$hash->{VERSION} = version->parse($VERSION)->normal; $hash->{VERSION} = version->parse($VERSION)->normal;
$hash->{NOTIFYDEV} = qq(global,$name); $hash->{NOTIFYDEV} = qq(global,$name);
$hash->{actionQueue} = []; $hash->{actionQueue} = [];
$hash->{helper}->{loginerr} = 0;
::CommandAttr( undef, $name . q{ room Tesla} ) ::CommandAttr( undef, $name . q{ room Tesla} )
if ( ::AttrVal( $name, 'room', 'none' ) eq 'none' ); if ( ::AttrVal( $name, 'room', 'none' ) eq 'none' );
::Log3( $name, 3, ::Log3 $name, 3,
"TeslaPowerwall2AC ($name) - defined TeslaPowerwall2AC Device with Host $host and Interval $hash->{INTERVAL}" "TeslaPowerwall2AC ($name) - defined TeslaPowerwall2AC Device with Host $host and Interval $hash->{INTERVAL}";
);
### create password object to handle pass keystore ### create password object to handle pass keystore
$hash->{helper}->{passObj} = $hash->{helper}->{passObj} =
@ -185,7 +185,7 @@ sub Undef {
my $name = shift; my $name = shift;
::RemoveInternalTimer($hash); ::RemoveInternalTimer($hash);
::Log3( $name, 3, "TeslaPowerwall2AC ($name) - Device $name deleted" ); ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - Device $name deleted";
return; return;
} }
@ -198,11 +198,11 @@ sub Attr {
if ( $cmd eq 'set' && $attrVal eq '1' ) { if ( $cmd eq 'set' && $attrVal eq '1' ) {
::RemoveInternalTimer($hash); ::RemoveInternalTimer($hash);
::readingsSingleUpdate( $hash, 'state', 'disabled', 1 ); ::readingsSingleUpdate( $hash, 'state', 'disabled', 1 );
::Log3( $name, 3, "TeslaPowerwall2AC ($name) - disabled" ); ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - disabled";
} }
elsif ( $cmd eq 'del' ) { elsif ( $cmd eq 'del' ) {
::Log3( $name, 3, "TeslaPowerwall2AC ($name) - enabled" ); ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - enabled";
} }
} }
@ -211,13 +211,12 @@ sub Attr {
return return
'check disabledForIntervals Syntax HH:MM-HH:MM or \'HH:MM-HH:MM HH:MM-HH:MM ...\'' 'check disabledForIntervals Syntax HH:MM-HH:MM or \'HH:MM-HH:MM HH:MM-HH:MM ...\''
unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/x ); unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/x );
::Log3( $name, 3, ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - disabledForIntervals";
"TeslaPowerwall2AC ($name) - disabledForIntervals" );
::readingsSingleUpdate( $hash, 'state', 'disabled', 1 ); ::readingsSingleUpdate( $hash, 'state', 'disabled', 1 );
} }
elsif ( $cmd eq 'del' ) { elsif ( $cmd eq 'del' ) {
::Log3( $name, 3, "TeslaPowerwall2AC ($name) - enabled" ); ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - enabled";
::readingsSingleUpdate( $hash, 'state', 'active', 1 ); ::readingsSingleUpdate( $hash, 'state', 'active', 1 );
} }
} }
@ -225,9 +224,8 @@ sub Attr {
if ( $attrName eq 'interval' ) { if ( $attrName eq 'interval' ) {
if ( $cmd eq 'set' ) { if ( $cmd eq 'set' ) {
if ( $attrVal < 60 ) { if ( $attrVal < 60 ) {
::Log3( $name, 3, ::Log3 $name, 3,
"TeslaPowerwall2AC ($name) - interval too small, please use something >= 60 (sec), default is 300 (sec)" "TeslaPowerwall2AC ($name) - interval too small, please use something >= 60 (sec), default is 300 (sec)";
);
return return
q{interval too small, please use something >= 60 (sec), default is 300 (sec)}; q{interval too small, please use something >= 60 (sec), default is 300 (sec)};
@ -235,16 +233,16 @@ q{interval too small, please use something >= 60 (sec), default is 300 (sec)};
else { else {
::RemoveInternalTimer($hash); ::RemoveInternalTimer($hash);
$hash->{INTERVAL} = $attrVal; $hash->{INTERVAL} = $attrVal;
::Log3( $name, 3, ::Log3 $name, 3,
"TeslaPowerwall2AC ($name) - set interval to $attrVal" ); "TeslaPowerwall2AC ($name) - set interval to $attrVal";
Timer_GetData($hash); Timer_GetData($hash);
} }
} }
elsif ( $cmd eq 'del' ) { elsif ( $cmd eq 'del' ) {
::RemoveInternalTimer($hash); ::RemoveInternalTimer($hash);
$hash->{INTERVAL} = 300; $hash->{INTERVAL} = 300;
::Log3( $name, 3, ::Log3 $name, 3,
"TeslaPowerwall2AC ($name) - set interval to default" ); "TeslaPowerwall2AC ($name) - set interval to default";
Timer_GetData($hash); Timer_GetData($hash);
} }
} }
@ -307,13 +305,15 @@ sub Get {
return 'Unknown argument ' . $cmd . ', choose one of ' . $list; return 'Unknown argument ' . $cmd . ', choose one of ' . $list;
} }
$hash->{helper}->{loginerr} = 0 if $cmd eq 'login';
} }
return 'There are still path commands in the action queue' return 'There are still path commands in the action queue'
if ( defined( $hash->{actionQueue} ) if ( defined( $hash->{actionQueue} )
&& scalar( @{ $hash->{actionQueue} } ) > 0 ); && scalar( @{ $hash->{actionQueue} } ) > 0 );
unshift( @{ $hash->{actionQueue} }, $arg ); unshift @{ $hash->{actionQueue} }, $arg;
Write($hash); Write($hash);
return; return;
@ -384,7 +384,7 @@ sub Set { ## no critic (Subroutine with high complexity score)
return 'Unknown argument ' . $cmd . ', choose one of ' . $list; return 'Unknown argument ' . $cmd . ', choose one of ' . $list;
} }
unshift( @{ $hash->{actionQueue} }, $arg ); unshift @{ $hash->{actionQueue} }, $arg;
Write($hash); Write($hash);
return; return;
@ -416,11 +416,11 @@ sub Timer_GetData {
); );
if ( !defined( $hash->{TOKEN} ) ) { if ( !defined( $hash->{TOKEN} ) ) {
unshift( @{ $hash->{actionQueue} }, 'login' ); unshift @{ $hash->{actionQueue} }, 'login';
} }
else { else {
while ( my $obj = each %paths ) { while ( my $obj = each %paths ) {
unshift( @{ $hash->{actionQueue} }, $obj ); unshift @{ $hash->{actionQueue} }, $obj;
} }
} }
@ -434,8 +434,8 @@ sub Timer_GetData {
::InternalTimer( ::gettimeofday() + $hash->{INTERVAL}, ::InternalTimer( ::gettimeofday() + $hash->{INTERVAL},
\&FHEM::Devices::Tesla::Powerwall::Timer_GetData, $hash ); \&FHEM::Devices::Tesla::Powerwall::Timer_GetData, $hash );
::Log3( $name, 4, ::Log3 $name, 4,
"TeslaPowerwall2AC ($name) - Call ::InternalTimer Timer_GetData" ); "TeslaPowerwall2AC ($name) - Call ::InternalTimer Timer_GetData";
return; return;
} }
@ -472,8 +472,8 @@ sub Write {
} }
); );
return ::Log3( $name, 4, return ::Log3 $name, 4,
"TeslaPowerwall2AC ($name) - Send with URI: https://$uri" ); "TeslaPowerwall2AC ($name) - Send with URI: https://$uri";
} }
sub ErrorHandling { sub ErrorHandling {
@ -494,8 +494,7 @@ sub ErrorHandling {
::readingsBulkUpdate( $hash, 'lastRequestError', $err, 1 ); ::readingsBulkUpdate( $hash, 'lastRequestError', $err, 1 );
::readingsEndUpdate( $hash, 1 ); ::readingsEndUpdate( $hash, 1 );
::Log3( $name, 3, ::Log3 $name, 3, "TeslaPowerwall2AC ($name) - RequestERROR: $err";
"TeslaPowerwall2AC ($name) - RequestERROR: $err" );
$hash->{actionQueue} = []; $hash->{actionQueue} = [];
return; return;
@ -512,21 +511,38 @@ sub ErrorHandling {
::readingsBulkUpdate( $hash, 'lastRequestError', $param->{code}, 1 ); ::readingsBulkUpdate( $hash, 'lastRequestError', $param->{code}, 1 );
::Log3( $name, 3, ::Log3 $name, 3,
"TeslaPowerwall2AC ($name) - RequestERROR: $param->{code}" ); "TeslaPowerwall2AC ($name) - RequestERROR: $param->{code}";
::readingsEndUpdate( $hash, 1 ); ::readingsEndUpdate( $hash, 1 );
::Log3( $name, 5, ::Log3 $name, 5,
"TeslaPowerwall2AC ($name) - RequestERROR: received http code $param->{code} without any data after requesting" "TeslaPowerwall2AC ($name) - RequestERROR: received http code $param->{code} without any data after requesting";
);
$hash->{actionQueue} = []; $hash->{actionQueue} = [];
return; return;
} }
## Fehler für neuen Token
## {"code":401,"error":"bad credentials","message":"Login Error"}
if ( $data =~ m#{"code":(\d+),"error":"(.+)","message":"(.+)"}$#xms ) { if ( $data =~ m#{"code":(\d+),"error":"(.+)","message":"(.+)"}$#xms ) {
if ( $1 == 401
&& $2 eq 'bad credentials'
&& $3 eq 'Login Error'
&& $hash->{helper}->{loginerr} == 0 )
{
$hash->{helper}->{loginerr} = 1;
$hash->{actionQueue} = [];
unshift @{ $hash->{actionQueue} }, 'login';
return Write($hash);
}
$hash->{helper}->{loginerr} = 0;
::readingsBeginUpdate($hash); ::readingsBeginUpdate($hash);
::readingsBulkUpdate( $hash, 'state', $1, 1 ); ::readingsBulkUpdate( $hash, 'state', $1, 1 );
@ -552,7 +568,7 @@ sub ErrorHandling {
if ( defined( $hash->{actionQueue} ) if ( defined( $hash->{actionQueue} )
&& scalar( @{ $hash->{actionQueue} } ) > 0 ); && scalar( @{ $hash->{actionQueue} } ) > 0 );
::Log3( $name, 4, "TeslaPowerwall2AC ($name) - Recieve JSON data: $data" ); ::Log3 $name, 4, "TeslaPowerwall2AC ($name) - Recieve JSON data: $data";
return ResponseProcessing( $hash, $param->{setCmd}, $data ); return ResponseProcessing( $hash, $param->{setCmd}, $data );
} }
@ -568,8 +584,7 @@ sub ResponseProcessing {
$decode_json = eval { decode_json($json) }; $decode_json = eval { decode_json($json) };
if ($@) { if ($@) {
::Log3( $name, 4, ::Log3 $name, 4, "TeslaPowerwall2AC ($name) - error while request: $@";
"TeslaPowerwall2AC ($name) - error while request: $@" );
::readingsBeginUpdate($hash); ::readingsBeginUpdate($hash);
::readingsBulkUpdate( $hash, 'JSON Error', $@ ); ::readingsBulkUpdate( $hash, 'JSON Error', $@ );
::readingsBulkUpdate( $hash, 'state', 'JSON error' ); ::readingsBulkUpdate( $hash, 'state', 'JSON error' );
@ -616,7 +631,7 @@ sub WriteReadings {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
::Log3( $name, 4, "TeslaPowerwall2AC ($name) - Write Readings" ); ::Log3 $name, 4, "TeslaPowerwall2AC ($name) - Write Readings";
::readingsBeginUpdate($hash); ::readingsBeginUpdate($hash);
while ( my ( $r, $v ) = each %{$readings} ) { while ( my ( $r, $v ) = each %{$readings} ) {
@ -868,13 +883,13 @@ sub CreateUri {
my $hash = shift; my $hash = shift;
my $path = shift; my $path = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $host = $hash->{HOST}; my $host = $hash->{HOST};
my $header = ( my $header =
defined( $hash->{TOKEN} ) defined( $hash->{TOKEN} )
? 'Cookie: AuthCookie=' . $hash->{TOKEN} ? 'Cookie: AuthCookie=' . $hash->{TOKEN}
: undef : undef;
);
my $method = 'GET'; my $method = 'GET';
my $uri = ( my $uri = (
$path ne 'login' $path ne 'login'
@ -899,7 +914,7 @@ sub CreateUri {
$uri = $host . '/api/' . $cmdPaths{$path}; $uri = $host . '/api/' . $cmdPaths{$path};
} }
return ( $uri, $method, $header, $data, $path ); return $uri, $method, $header, $data, $path;
} }
sub Rename { sub Rename {
@ -912,15 +927,13 @@ sub Rename {
( $passResp, $passErr ) = ( $passResp, $passErr ) =
$hash->{helper}->{passObj}->setRename( $new, $old ); $hash->{helper}->{passObj}->setRename( $new, $old );
::Log3( $new, 1, ::Log3 $new, 1,
"TeslaPowerwall2AC ($new) - error while change the password hash after rename - $passErr" "TeslaPowerwall2AC ($new) - error while change the password hash after rename - $passErr"
)
if (!defined($passResp) if (!defined($passResp)
&& defined($passErr) ); && defined($passErr) );
::Log3( $new, 1, ::Log3 $new, 1,
"TeslaPowerwall2AC ($new) - change password hash after rename successfully" "TeslaPowerwall2AC ($new) - change password hash after rename successfully"
)
if ( defined($passResp) if ( defined($passResp)
&& !defined($passErr) ); && !defined($passErr) );