diff --git a/bundles/org.openhab.binding.ecobee/README.md b/bundles/org.openhab.binding.ecobee/README.md index edac7608e10..69bb244c225 100644 --- a/bundles/org.openhab.binding.ecobee/README.md +++ b/bundles/org.openhab.binding.ecobee/README.md @@ -57,14 +57,14 @@ After you have installed the binding, you can create the Account thing using the Once the Account thing is created, the binding will try to get information about your thermostats from the Ecobee web service. When this happens, the binding will determine that it has not yet been authorized by the Ecobee web service. -At this point the binding will retrieve a four-character PIN code from the Ecobee web service. +At this point the binding will retrieve a multi-character PIN code from the Ecobee web service. The binding will mark the Account thing OFFLINE with a detailed status message that contains the PIN code needed to complete the authorization. -The PIN code will be valid for 9 minutes. +The PIN code will be valid for several minutes. The status message will look something like this. ``` -Enter PIN 'RVLA' in MyApps. PIN expires in 9 minutes. +Enter PIN 'JULO-RVLA' in MyApps. PIN expires in 239 minutes. ``` To complete the authorization, the PIN code must be entered into the Ecobee **My Apps** settings in your account at ecobee.com. @@ -72,6 +72,28 @@ This will authorize the binding to work with the thermostats associated with you Once authorization is complete, the binding will retrieve information about the available thermostats, and add those thermostats to the inbox. +## Ecobee Authorization Changes Effective 1 December 2020 + +Effective 1 Dec 2020, Ecobee implemented changes to their authorization process. +Ecobee recommends that users who authorized with Ecobee prior to 1 Dec 2020 should reauthorize their application as the new process affords greater security. +While the binding will continue to work using the old authorization method, it's recommended that you reauthorize the binding using the following process. + +- You may need to update openHAB to get the latest version of the binding + +- In the MyApps section of your Ecobee Portal, remove the application using the **Remove App** function. + +- Wait up to one hour for the binding to do a token refresh with the Ecobee servers. + +- At this point the Ecobee Account thing should be OFFLINE with a CONFIGURATION_PENDING status. + +- In the MyApps section of your Ecobee Portal, re-add the binding using the **Add Application** function. +Use the PIN code that is displayed in the Ecobee Account thing status, or in the log file. + +- Confirm that the binding is again communicating with the Ecobee servers. +You can do this by verifying that your items are updating, or by putting the binding in DEBUG mode and monitoring the log file. + +- Post any issues on the forum. + ## Thing Configuration ### Ecobee Account diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java index de068f7a309..1d0bfd333ef 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java @@ -172,11 +172,22 @@ public class EcobeeApi implements AccessTokenRefreshListener { } catch (OAuthResponseException e) { logger.info("API: Exception getting access token: error='{}', description='{}'", e.getError(), e.getErrorDescription()); - // How to handle the possible error codes? + handleOAuthException(e); } return isAuthorized; } + private void handleOAuthException(OAuthResponseException e) { + if ("invalid_grant".equalsIgnoreCase(e.getError())) { + logger.warn("API: Received invalid_grant error response. User needs to reauthorize with Ecobee"); + deleteOAuthClientService(); + createOAuthClientService(); + } else { + // How to handle other possible error codes? + logger.warn("API: Don't know how to handle '{}' error response", e.getError()); + } + } + @Override public void onAccessTokenResponse(AccessTokenResponse accessTokenResponse) { } @@ -308,10 +319,8 @@ public class EcobeeApi implements AccessTokenRefreshListener { } private boolean isSuccess(@Nullable AbstractResponseDTO response) { - boolean success = true; if (response == null) { logger.info("API: Ecobee API returned null response"); - success = false; } else if (response.status.code.intValue() != 0) { logger.info("API: Ecobee API returned unsuccessful status: code={}, message={}", response.status.code, response.status.message); @@ -323,13 +332,16 @@ public class EcobeeApi implements AccessTokenRefreshListener { } else if (response.status.code == ECOBEE_TOKEN_EXPIRED) { // Check isAuthorized again to see if we can get a valid token logger.info("API: Unable to complete API call because token is expired"); - if (!isAuthorized()) { + if (isAuthorized()) { + return true; + } else { logger.warn("API: isAuthorized was NOT successful on second try"); } } - success = false; + } else { + return true; } - return success; + return false; } private Properties setHeaders() throws EcobeeAuthException { diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeAuth.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeAuth.java index 4f6831e89fd..305d1bebfe1 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeAuth.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeAuth.java @@ -80,6 +80,7 @@ public class EcobeeAuth { this.bridgeHandler = bridgeHandler; pinExpirationTime = 0; state = EcobeeAuthState.NEED_PIN; + authResponse = null; } public void setState(EcobeeAuthState newState) {