diff --git a/98_TadoAPI.pm b/98_TadoAPI.pm index 1f32f3a..49a197c 100644 --- a/98_TadoAPI.pm +++ b/98_TadoAPI.pm @@ -170,21 +170,21 @@ sub TadoAPI_Set(@) { } elsif( $cmd eq 'setZoneOverlay' ) { Log3 $name, 5, "TadoAPI $name" . ": " . "processing ($cmd)"; - return "Need at least two parameters (ZoneID, Setting)" if(@a < 4); + return "Need at least two parameters (ZoneID, Setting) - Setting: off=delete overlay; 0=heating power off; 1<=desired temperature (overlay)" if(@a < 4); if( $a[3] eq "off" ) { TadoAPI_SetZoneOverlayById($hash, $value, "off"); - } elsif ($a[3] > 1) { + } elsif ($a[3] >= 0) { TadoAPI_SetZoneOverlayById($hash, $value, $a[3]); } Log3 $name, 3, "TadoAPI $name" . ": " . "$cmd finished\n"; } elsif( $cmd eq 'setAllOverlays' ) { Log3 $name, 5, "TadoAPI $name" . ": " . "processing ($cmd)"; - return "Need at least one parameter (Setting)" if(@a < 3); + return "Need at least one parameter (Setting) - Setting: off=delete overlay; 0=heating power off; 1<=desired temperature (overlay)" if(@a < 3); if( $value eq "off" ) { TadoAPI_SetAllOverlays($hash, "off"); - } elsif ($value > 1) { + } elsif ($value >= 0) { TadoAPI_SetAllOverlays($hash, $value); } Log3 $name, 3, "TadoAPI $name" . ": " . "$cmd finished\n"; @@ -379,7 +379,7 @@ sub TadoAPI_LoadToken(@){ }else{ Log3 $name, 5, "TadoAPI $name" . ": " . "Token expires at " . localtime($tokenLifeTime); # if token is about to expire, refresh him - if(($tokenLifeTime-15) < gettimeofday()){ + if(($tokenLifeTime-45) < gettimeofday()){ Log3 $name, 5, "TadoAPI $name" . ": " . "Token will expire soon, refreshing"; TadoAPI_TokenRefresh($hash); } @@ -391,89 +391,116 @@ return undef; } sub TadoAPI_NewTokenRequest(@) { - my ($hash) = @_; - my $name = $hash->{NAME}; - my $username = $hash->{TADO_USER}; - my $password = TadoAPI_readPassword($name); - my $tokenFileName = $tokenFile."_".$name; + my ($hash) = @_; + my $name = $hash->{NAME}; + my $username = $hash->{TADO_USER}; + my $password = TadoAPI_readPassword($name); + my $tokenFileName = $tokenFile."_".$name; - Log3 $name, 5, "TadoAPI $name" . ": " . "calling NewTokenRequest()"; + Log3 $name, 5, "TadoAPI $name" . ": " . "calling NewTokenRequest()"; - $data = { - client_id => $client_id, - client_secret => $client_secret, - username => $username, - password => $password, - scope => $scope, - grant_type=>'password' - }; + $data = { + client_id => $client_id, + client_secret => $client_secret, + username => $username, + password => $password, + scope => $scope, + grant_type=>'password' + }; - my $param = { - url => $AuthURL, - method => 'POST', - timeout => 5, - hash => $hash, - data => $data - }; + my $param = { + url => $AuthURL, + method => 'POST', + timeout => 5, + hash => $hash, + data => $data + }; - Log3 $name, 5, 'Blocking GET: ' . Dumper($param); - my ($err, $data) = HttpUtils_BlockingGet($param); + Log3 $name, 5, 'Blocking GET: ' . Dumper($param); + my ($err, $data) = HttpUtils_BlockingGet($param); - if($err ne "") - { - Log3 $name, 3, "TadoAPI $name" . ": " . "NewTokenRequest: Error while requesting ".$param->{url}." - $err"; - } - elsif($data ne "") - { - Log3 $name, 5, "url ".$param->{url}." returned: $data"; - my $decoded_data = eval { decode_json($data) }; - if ($@){ - Log3 $name, 3, "TadoAPI $name" . ": " . "NewTokenRequest: decode_json failed, invalid json. error: $@ "; - }else{ - #write token data in file - open(TOKENFILE,">$tokenFileName") or die("ERROR: $!"); - print TOKENFILE $data . "\n"; - close(TOKENFILE); - - # token lifetime management - $hash->{TOKEN_LIFETIME} = gettimeofday() + $decoded_data->{'expires_in'}; - $hash->{TOKEN_LIFETIME_HR} = localtime($hash->{TOKEN_LIFETIME}); - Log3 $name, 5, "TadoAPI $name" . ": " . "Retrived new authentication token successfully. Valid until " . localtime($hash->{TOKEN_LIFETIME}); - $hash->{STATE}="reachable"; - } + if($err ne "") + { + Log3 $name, 3, "TadoAPI $name" . ": " . "NewTokenRequest: Error while requesting ".$param->{url}." - $err"; + } + elsif($data ne "") + { + Log3 $name, 5, "url ".$param->{url}." returned: $data"; + my $decoded_data = eval { decode_json($data) }; + if ($@){ + Log3 $name, 3, "TadoAPI $name" . ": " . "NewTokenRequest: decode_json failed, invalid json. error: $@ "; + }else{ + #write token data in file + open(TOKENFILE,">$tokenFileName") or die("ERROR: $!"); + print TOKENFILE $data . "\n"; + close(TOKENFILE); + + # token lifetime management + $hash->{TOKEN_LIFETIME} = gettimeofday() + $decoded_data->{'expires_in'}; + $hash->{TOKEN_LIFETIME_HR} = localtime($hash->{TOKEN_LIFETIME}); + Log3 $name, 5, "TadoAPI $name" . ": " . "Retrived new authentication token successfully. Valid until " . localtime($hash->{TOKEN_LIFETIME}); + $hash->{STATE}="reachable"; } + } } sub TadoAPI_TokenRefresh(@) { - my ($hash) = @_; - my $name = $hash->{NAME}; + my ($hash) = @_; + my $name = $hash->{NAME}; + my $tokenFileName = $tokenFile."_".$name; - Log3 $name, 5, "TadoAPI $name" . ": " . "calling TokenRefresh()"; + # load token + eval { + open(TOKENFILE, '<', $hash->{TOKEN_FILE}) or die("ERROR: $!"); + $TokenData = decode_json()}; - # load token - eval { - open(TOKENFILE, '<', $hash->{TOKEN_FILE}) or die("ERROR: $!"); - $TokenData = decode_json()}; + $data = { + client_id => $client_id, + client_secret => $client_secret, + scope => $scope, + grant_type=>'refresh_token', + refresh_token => $TokenData->{'refresh_token'} + }; - $data = { - client_id => $client_id, - client_secret => $client_secret, - scope => $scope, - grant_type=>'refresh_token', - refresh_token => $TokenData->{'refresh_token'} - }; + my $param = { + url => $AuthURL, + method => 'POST', + timeout => 5, + hash => $hash, + data => $data + }; - my $request = { - url => $AuthURL, - method => 'POST', - timeout => 5, - callback => \&Tado_StoreTokenCallback, - hash => $hash, - data => $data - }; + Log3 $name, 5, 'Blocking GET TokenRefresh: ' . Dumper($param); + my ($err, $data) = HttpUtils_BlockingGet($param); - Log3 $name, 3, "TadoAPI $name" . ": " . "Calling refresh token..."; - HttpUtils_NonblockingGet($request); + if($err ne "") + { + Log3 $name, 3, "TadoAPI $name" . ": " . "TokenRefresh: Error in token retrival while requesting ".$param->{url}." - $err"; + $hash->{STATE}="error"; + } + + elsif($data ne "") + { + Log3 $name, 5, "url ".$param->{url}." returned: $data"; + + my $decoded_data = eval{decode_json($data);}; + + if ($@){ + Log3 $name, 3, "TadoAPI $name" . ": " . "TokenRefresh: decode_json failed, invalid json. error:$@\n" if $@; + $hash->{STATE}="error"; + }else{ + #write token data in file + open(TOKENFILE,">$tokenFileName") or die("ERROR: $!"); + print TOKENFILE $data . "\n"; + close(TOKENFILE); + + # token lifetime management + $hash->{TOKEN_LIFETIME} = gettimeofday() + $decoded_data->{'expires_in'}; + $hash->{TOKEN_LIFETIME_HR} = localtime($hash->{TOKEN_LIFETIME}); + Log3 $name, 5, "TadoAPI $name" . ": " . "TokenRefresh: Refreshed authentication token successfully. Valid until " . localtime($hash->{TOKEN_LIFETIME}); + $hash->{STATE}="reachable"; + } + } } sub TadoAPI_Update(@){ @@ -519,7 +546,19 @@ sub TadoAPI_SetZoneOverlayById(@){ if ($setting eq "off"){ $method = "DELETE"; Log3 $name, 3, "TadoAPI $name" . ": " . "Deleting Overlay for Zone $zoneID"; - }elsif($setting > 10){ + }elsif($setting == 0){ + $method = "PUT"; + $myjson = { + setting => { + type => "HEATING", + power => "OFF", + }, + termination => { + type => "MANUAL" + }, + }; + $myjson = encode_json($myjson); + }elsif($setting > 0){ $method = "PUT"; $myjson = { setting => { @@ -540,7 +579,7 @@ sub TadoAPI_SetZoneOverlayById(@){ url => $URL, header => { "Content-Type"=>"application/json;charset=UTF-8","Authorization" => "$TokenData->{'token_type'} $TokenData->{'access_token'}" }, method => $method, - timeout => 3, + timeout => 5, callback => \&Tado_UpdateZoneOverlayCallback, hash => $hash, setting => $setting, @@ -548,8 +587,7 @@ sub TadoAPI_SetZoneOverlayById(@){ data => $myjson }; - #Log3 $name, 3, 'NonBlocking Request: ' . Dumper($request); - + Log3 $name, 5, 'NonBlocking Request: ' . Dumper($request); HttpUtils_NonblockingGet($request); } @@ -570,44 +608,8 @@ sub TadoAPI_SetAllOverlays(@){ my $myjson =""; for (my $i=1; $i <= $zonecount; $i++) { - my $URL = $QueryURL . qq{/$homeID/zones/$i/overlay}; - - if ($setting eq "off"){ - $method = "DELETE"; - Log3 $name, 3, "TadoAPI $name" . ": " . "Deleting Overlay for Zone $i"; - }elsif($setting > 10){ - $method = "PUT"; - $myjson = { - setting => { - type => "HEATING", - power => "ON", - temperature => { - celsius => $setting - }, - }, - termination => { - type => "MANUAL" - }, - }; - $myjson = encode_json($myjson); - } - - my $request = { - url => $URL, - header => { "Content-Type"=>"application/json;charset=UTF-8","Authorization" => "$TokenData->{'token_type'} $TokenData->{'access_token'}" }, - method => $method, - timeout => 10, - callback => \&Tado_UpdateZoneOverlayCallback, - hash => $hash, - setting => $setting, - zoneID => $i, - data => $myjson - }; - HttpUtils_NonblockingGet($request); - + TadoAPI_SetZoneOverlayById($hash, $i, $setting); } - # finaly update readings - #TadoAPI_UpdateFn($hash); } } @@ -661,6 +663,7 @@ sub TadoAPI_UpdateFn(@){ header => { "Content-Type"=>"application/json;charset=UTF-8","Authorization" => "$TokenData->{'token_type'} $TokenData->{'access_token'}" }, method => 'GET', timeout => 10, + incrementalTimout => 1, hash => $hash, callback => \&TadoAPI_UpdateAllZonesCallback }; @@ -668,26 +671,26 @@ sub TadoAPI_UpdateFn(@){ HttpUtils_NonblockingGet($request); # mobile devices - $TokenData = TadoAPI_LoadToken($hash); $URL=$QueryURL . qq{/$homeID/mobileDevices}; $request = { url => $URL, header => { "Content-Type"=>"application/json;charset=UTF-8","Authorization" => "$TokenData->{'token_type'} $TokenData->{'access_token'}" }, method => 'GET', - timeout => 5, + timeout => 6, + incrementalTimout => 1, callback => \&TadoAPI_UpdateMobileReadingsCallback, hash => $hash }; HttpUtils_NonblockingGet($request); # tado devices - $TokenData = TadoAPI_LoadToken($hash); $URL=$QueryURL.qq{/$homeID/zones}; $request = { url => $URL, header => { "Content-Type"=>"application/json;charset=UTF-8","Authorization" => "$TokenData->{'token_type'} $TokenData->{'access_token'}" }, method => 'GET', timeout => 8, + incrementalTimout => 1, callback => \&TadoAPI_UpdateTadoDeviceInformationCallback, hash => $hash }; @@ -758,43 +761,6 @@ sub TadoAPI_callback($){ return undef; } -sub Tado_StoreTokenCallback($) -{ - my ($param, $err, $data) = @_; - my $hash = $param->{hash}; - my $name = $hash->{NAME}; - my $tokenFileName = $hash->{TOKEN_FILE}; - - if($err ne "") - { - Log3 $name, 3, "TadoAPI $name" . ": " . "StoreTokenCallback: Error in token retrival while requesting ".$param->{url}." - $err"; - $hash->{STATE}="error"; - } - - elsif($data ne "") - { - Log3 $name, 5, "url ".$param->{url}." returned: $data"; - - my $decoded_data = eval{decode_json($data);}; - - if ($@){ - Log3 $name, 3, "TadoAPI $name" . ": " . "StoreTokenCallback: decode_json failed, invalid json. error:$@\n" if $@; - $hash->{STATE}="error"; - }else{ - #write token data in file - open(TOKENFILE,">$tokenFileName") or die("ERROR: $!"); - print TOKENFILE $data . "\n"; - close(TOKENFILE); - - # token lifetime management - $hash->{TOKEN_LIFETIME} = gettimeofday() + $decoded_data->{'expires_in'}; - $hash->{TOKEN_LIFETIME_HR} = localtime($hash->{TOKEN_LIFETIME}); - Log3 $name, 5, "TadoAPI $name" . ": " . "StoreTokenCallback: Refreshed authentication token successfully. Valid until " . localtime($hash->{TOKEN_LIFETIME}); - $hash->{STATE}="reachable"; - } - } -} - sub Tado_UpdateZoneOverlayCallback($) { my ($param, $err, $data) = @_;