From 95259b1095b9431977480782b8c111488211a425 Mon Sep 17 00:00:00 2001 From: Georg Siebke <53263304+georg138@users.noreply.github.com> Date: Tue, 9 Feb 2021 22:03:22 +0100 Subject: [PATCH] [somfytahoma] Retry command submission when tahoma gateway is busy. (#10023) * Retry command submission when tahome gateway is busy. * Changed log level, cosmetic changes * Store list of scheduled retries; cancelled when handler is disposed. * Made retryFutures thread-safe Signed-off-by: Georg Siebke --- .../internal/config/SomfyTahomaConfig.java | 18 ++++++++++ .../handler/SomfyTahomaBridgeHandler.java | 34 +++++++++++++++++-- .../main/resources/OH-INF/config/config.xml | 12 +++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java index 6b2e49a94..5ead6ad4d 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java @@ -26,6 +26,8 @@ public class SomfyTahomaConfig { private String password = ""; private int refresh = 30; private int statusTimeout = 300; + private int retries = 10; + private int retryDelay = 1000; public String getEmail() { return email; @@ -43,6 +45,14 @@ public class SomfyTahomaConfig { return statusTimeout; } + public int getRetries() { + return retries; + } + + public int getRetryDelay() { + return retryDelay; + } + public void setEmail(String email) { this.email = email; } @@ -50,4 +60,12 @@ public class SomfyTahomaConfig { public void setPassword(String password) { this.password = password; } + + public void setRetries(int retries) { + this.retries = retries; + } + + public void setRetryDelay(int retryDelay) { + this.retryDelay = retryDelay; + } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java index 9d9b6dcb5..c71acdfdc 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java @@ -18,6 +18,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -78,6 +79,9 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler { */ private @Nullable ScheduledFuture reconciliationFuture; + // List of futures used for command retries + private Collection> retryFutures = new ConcurrentLinkedQueue>(); + /** * List of executions */ @@ -275,6 +279,9 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler { logger.debug("Doing cleanup"); stopPolling(); executions.clear(); + // cancel all scheduled retries + retryFutures.forEach(x -> x.cancel(false)); + try { httpClient.stop(); } catch (Exception e) { @@ -561,13 +568,23 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler { return; } - Boolean result = sendCommandInternal(io, command, params, url); + removeFinishedRetries(); + + boolean result = sendCommandInternal(io, command, params, url); if (!result) { - sendCommandInternal(io, command, params, url); + scheduleRetry(io, command, params, url, thingConfig.getRetries()); } } - private Boolean sendCommandInternal(String io, String command, String params, String url) { + private void repeatSendCommandInternal(String io, String command, String params, String url, int retries) { + logger.debug("Retrying command, retries left: {}", retries); + boolean result = sendCommandInternal(io, command, params, url); + if (!result && (retries > 0)) { + scheduleRetry(io, command, params, url, retries - 1); + } + } + + private boolean sendCommandInternal(String io, String command, String params, String url) { String value = params.equals("[]") ? command : params.replace("\"", ""); String urlParameters = "{\"label\":\"" + getThingLabelByURL(io) + " - " + value + " - OH2\",\"actions\":[{\"deviceURL\":\"" + io + "\",\"commands\":[{\"name\":\"" + command @@ -587,6 +604,17 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler { return false; } + private void removeFinishedRetries() { + retryFutures.removeIf(x -> x.isDone()); + logger.debug("Currently {} retries are scheduled.", retryFutures.size()); + } + + private void scheduleRetry(String io, String command, String params, String url, int retries) { + retryFutures.add(scheduler.schedule(() -> { + repeatSendCommandInternal(io, command, params, url, retries); + }, thingConfig.getRetryDelay(), TimeUnit.MILLISECONDS)); + } + private String getThingLabelByURL(String io) { Thing th = getThingByDeviceUrl(io); if (th != null) { diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/OH-INF/config/config.xml index 57a49c27b..3f2f09e3b 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/OH-INF/config/config.xml @@ -45,5 +45,17 @@ Specifies the timeout in seconds after which the status is got from Tahoma cloud 300 + + + + Specifies the number of retries when command execution + 10 + + + + + Specifies the delay in milliseconds between subsequent retries after a command failure + 1000 +