]> git.basschouten.com Git - openhab-addons.git/commitdiff
[somfytahoma] Improvements to avoid cloud login throttling (#15489)
authorOndrej Pecta <opecta@gmail.com>
Sat, 9 Sep 2023 10:43:08 +0000 (12:43 +0200)
committerGitHub <noreply@github.com>
Sat, 9 Sep 2023 10:43:08 +0000 (12:43 +0200)
* [somfytahoma] Improvements to avoid cloud login throttling
* [somfytahoma] add custom message to status display

---------

Signed-off-by: Ondrej Pecta <opecta@gmail.com>
bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/SomfyTahomaBindingConstants.java
bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java

index 81b36595f34d03c6c410764b398ba7e51c25524f..30edae823d4f0334b3d80d9124532d1da86a8831 100644 (file)
@@ -390,8 +390,10 @@ public class SomfyTahomaBindingConstants {
     public static final String AUTHENTICATION_OAUTH_GRANT_ERROR = "Provided Authorization Grant is invalid.";
     public static final String AUTHENTICATION_OAUTH_INVALID_GRANT = "error.invalid.grant";
     public static final String OPENHAB_TOKEN = "openHAB token";
-    public static final int SUSPEND_TIME = 120;
+    public static final int SUSPEND_TIME = 300;
     public static final int RECONCILIATION_TIME = 600;
+    public static final int LOGIN_LIMIT_TIME = 60;
+    public static final int MAX_ERRORS = 5;
 
     // Commands
     public static final String COMMAND_MY = "my";
index 5c032aee69584112e603c0224933360606a550e4..664530bf93e2f6192eb0fa34076929965fd5c794 100644 (file)
@@ -19,6 +19,7 @@ import java.net.InetAddress;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
+import java.time.Instant;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -139,6 +140,12 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
     // Cloud fallback
     private boolean cloudFallback = false;
 
+    // Communication errors counter
+    private int errorsCounter = 0;
+
+    // Last login timestamp
+    private Instant lastLoginTimestamp = Instant.MIN;
+
     /**
      * Our configuration
      */
@@ -240,8 +247,8 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
             return;
         }
 
-        if (tooManyRequests) {
-            logger.debug("Skipping login due to too many requests");
+        if (tooManyRequests || Instant.now().minusSeconds(LOGIN_LIMIT_TIME).isBefore(lastLoginTimestamp)) {
+            logger.debug("Postponing login to avoid throttling");
             return;
         }
 
@@ -277,6 +284,8 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
             SomfyTahomaLoginResponse data = gson.fromJson(response.getContentAsString(),
                     SomfyTahomaLoginResponse.class);
 
+            lastLoginTimestamp = Instant.now();
+
             if (data == null) {
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                         "Received invalid data (login)");
@@ -844,7 +853,7 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
 
     private Request sendRequestBuilderLocal(String subUrl, HttpMethod method) {
         return httpClient.newRequest(getApiFullUrl(subUrl)).method(method).accept("application/json")
-                .header(HttpHeader.AUTHORIZATION, "Bearer " + localToken);
+                .timeout(TAHOMA_TIMEOUT, TimeUnit.SECONDS).header(HttpHeader.AUTHORIZATION, "Bearer " + localToken);
     }
 
     /**
@@ -1123,6 +1132,7 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
                     response = sendDeleteToTahomaWithCookie(url);
                 default:
             }
+            errorsCounter = 0;
             return classOfT != null ? gson.fromJson(response, classOfT) : null;
         } catch (JsonSyntaxException e) {
             logger.debug("Received data: {} is not JSON", response, e);
@@ -1132,14 +1142,27 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Temporarily banned");
                 setTooManyRequests();
             } else if (isEventListenerTimeout(e)) {
+                logger.debug("Event listener timeout occurred", e);
                 reLogin();
+            } else if (isDevModeReady()) {
+                // the local gateway is unreachable
+                errorsCounter++;
+                logger.debug("Local gateway communication error", e);
+                discoverGateway();
+                if (errorsCounter > MAX_ERRORS) {
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                            "Too many communication errors");
+                }
             } else {
                 logger.debug("Cannot call url: {} with params: {}!", getApiFullUrl(url), urlParameters, e);
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
             }
         } catch (TimeoutException e) {
+            errorsCounter++;
             logger.debug("Timeout when calling url: {} with params: {}!", getApiFullUrl(url), urlParameters, e);
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
+            if (errorsCounter > MAX_ERRORS) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Too many timeouts");
+            }
         } catch (InterruptedException e) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
             Thread.currentThread().interrupt();