Skip to content

Commit

Permalink
[ecobee] Fix for error code 14 (token expired) (openhab#16467)
Browse files Browse the repository at this point in the history
* Remove AccessTokenRefreshListener

Signed-off-by: Mark Hilbush <mark@hilbush.com>
  • Loading branch information
mhilbush committed Mar 5, 2024
1 parent 9987215 commit ba06c0d
Showing 1 changed file with 21 additions and 14 deletions.
Expand Up @@ -46,13 +46,14 @@
import org.openhab.binding.ecobee.internal.function.FunctionRequest;
import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
import org.openhab.binding.ecobee.internal.util.ExceptionUtils;
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
import org.openhab.core.auth.client.oauth2.OAuthClientService;
import org.openhab.core.auth.client.oauth2.OAuthException;
import org.openhab.core.auth.client.oauth2.OAuthFactory;
import org.openhab.core.auth.client.oauth2.OAuthResponseException;
import org.openhab.core.io.net.http.HttpUtil;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -67,7 +68,7 @@
* @author Mark Hilbush - Initial contribution
*/
@NonNullByDefault
public class EcobeeApi implements AccessTokenRefreshListener {
public class EcobeeApi {

private static final Gson GSON = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantDeserializer())
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer())
Expand Down Expand Up @@ -124,22 +125,19 @@ public void createOAuthClientService() {
logger.debug("API: Creating OAuth Client Service for {}", bridgeUID);
OAuthClientService service = oAuthFactory.createOAuthClientService(bridgeUID, ECOBEE_TOKEN_URL, null, apiKey,
"", ECOBEE_SCOPE, false);
service.addAccessTokenRefreshListener(this);
ecobeeAuth = new EcobeeAuth(bridgeHandler, apiKey, apiTimeout, service, httpClient);
oAuthClientService = service;
}

public void deleteOAuthClientService() {
String bridgeUID = bridgeHandler.getThing().getUID().getAsString();
logger.debug("API: Deleting OAuth Client Service for {}", bridgeUID);
oAuthClientService.removeAccessTokenRefreshListener(this);
oAuthFactory.deleteServiceAndAccessToken(bridgeUID);
}

public void closeOAuthClientService() {
String bridgeUID = bridgeHandler.getThing().getUID().getAsString();
logger.debug("API: Closing OAuth Client Service for {}", bridgeUID);
oAuthClientService.removeAccessTokenRefreshListener(this);
oAuthFactory.ungetOAuthService(bridgeUID);
}

Expand Down Expand Up @@ -202,10 +200,6 @@ private void handleOAuthException(OAuthResponseException e) {
}
}

@Override
public void onAccessTokenResponse(AccessTokenResponse accessTokenResponse) {
}

public @Nullable SummaryResponseDTO performThermostatSummaryQuery() {
logger.debug("API: Perform thermostat summary query");
if (!isAuthorized()) {
Expand Down Expand Up @@ -245,8 +239,10 @@ public List<ThermostatDTO> performThermostatQuery(final @Nullable Set<String> th
if (response != null) {
try {
ThermostatResponseDTO thermostatsResponse = GSON.fromJson(response, ThermostatResponseDTO.class);
if (isSuccess(thermostatsResponse)) {
return thermostatsResponse.thermostatList;
if (thermostatsResponse != null && isSuccess(thermostatsResponse)) {
if (thermostatsResponse.thermostatList != null) {
return thermostatsResponse.thermostatList;
}
}
} catch (JsonSyntaxException e) {
logJSException(e, response);
Expand Down Expand Up @@ -343,15 +339,26 @@ private boolean isSuccess(@Nullable AbstractResponseDTO response) {
deleteOAuthClientService();
createOAuthClientService();
} else if (response.status.code == ECOBEE_TOKEN_EXPIRED) {
// Check isAuthorized again to see if we can get a valid token
logger.debug("API: Unable to complete API call because token is expired");
logger.debug("API: Unable to complete API call because token is expired. Try to refresh the token...");
// Log some additional debug information about the current AccessTokenResponse
AccessTokenResponse localAccessTokenResponse = accessTokenResponse;
if (localAccessTokenResponse != null) {
logger.debug("API: AccessTokenResponse created on: {}", localAccessTokenResponse.getCreatedOn());
logger.debug("API: AccessTokenResponse expires in: {}", localAccessTokenResponse.getExpiresIn());
}
// Recreating the OAuthClientService seems to be the only way to handle this error
closeOAuthClientService();
createOAuthClientService();
if (isAuthorized()) {
return true;
} else {
logger.debug("API: isAuthorized was NOT successful on second try");
logger.warn("API: isAuthorized was NOT successful on second try");
bridgeHandler.updateBridgeStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Unable to refresh access token");
}
}
} else {
bridgeHandler.updateBridgeStatus(ThingStatus.ONLINE);
return true;
}
return false;
Expand Down

0 comments on commit ba06c0d

Please sign in to comment.