]> git.basschouten.com Git - openhab-addons.git/commitdiff
[remoteopenhab] New setting to restart the SSE connection after inact… (#10063)
authorlolodomo <lg.hc@free.fr>
Sat, 6 Feb 2021 16:12:22 +0000 (17:12 +0100)
committerGitHub <noreply@github.com>
Sat, 6 Feb 2021 16:12:22 +0000 (17:12 +0100)
* [remoteopenhab] New setting to restart the SSE connection after inactivity

Fix #9680

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
* Review comments: doc

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
bundles/org.openhab.binding.remoteopenhab/README.md
bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/config/RemoteopenhabServerConfiguration.java
bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/handler/RemoteopenhabBridgeHandler.java
bundles/org.openhab.binding.remoteopenhab/src/main/java/org/openhab/binding/remoteopenhab/internal/rest/RemoteopenhabRestClient.java
bundles/org.openhab.binding.remoteopenhab/src/main/resources/OH-INF/thing/thing-types.xml

index 7193a614f9a829e095198de7c91c71becf0e1023..9d56fc1edcfc59bc1d3f8b634aa6036219a9a57f 100644 (file)
@@ -45,7 +45,8 @@ The `server` thing has the following configuration parameters:
 | restPath              | yes      | The subpath of the REST API on the remote openHAB server. Default is /rest                                |
 | token                 | no       | The token to use when the remote openHAB server is setup to require authorization to run its REST API.    |
 | accessibilityInterval | no       | Minutes between checking the remote server accessibility. 0 to disable the check. Default is 3.           |
-| aliveInterval         | no       | Number of last minutes to take into account to determine whether the remote server is alive. 0 to disable this feature. Default is 5. |
+| aliveInterval         | no       | Number of last minutes to consider when monitoring the receipt of events from the remote server. If an event is received during this interval, the remote server is considered alive and its accessibility will not be verified. Use 0 to disable this feature. Default is 5. |
+| restartIfNoActivity   | no       | Set it to true if you want to restart the connection (SSE) to the remote server when no events are received in the monitored interval. It is not necessary if the goal is to properly handle a short network outage (few seconds). This can be useful if you want to deal with a long network outage. Do not enable it if you remote server does not send events during the monitored interval under normal conditions, it will cause frequent restart of the connection and potential loss of events. Default is false. |
 
 The `thing` thing has the following configuration parameters:
 
index ad196ddc52a27938f2211420899f51cffc9d5ff2..dc894d07070f13241a258b4450e064677748c484 100644 (file)
@@ -174,9 +174,9 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
 
         updateStatus(ThingStatus.UNKNOWN);
 
-        scheduler.submit(this::checkConnection);
+        scheduler.submit(() -> checkConnection(false));
         if (config.accessibilityInterval > 0) {
-            startCheckConnectionJob(config.accessibilityInterval, config.aliveInterval);
+            startCheckConnectionJob(config.accessibilityInterval, config.aliveInterval, config.restartIfNoActivity);
         }
     }
 
@@ -343,7 +343,7 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
         }
     }
 
-    public void checkConnection() {
+    public void checkConnection(boolean restartSse) {
         logger.debug("Try the root REST API...");
         try {
             restClient.tryApi();
@@ -367,6 +367,9 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
                             "Dynamic creation of the channels for the remote server items failed");
                     stopStreamingUpdates();
                 }
+            } else if (restartSse) {
+                logger.debug("The SSE connection is restarted because there was no recent event received");
+                restartStreamingUpdates();
             }
         } catch (RemoteopenhabException e) {
             logger.debug("{}", e.getMessage());
@@ -375,7 +378,7 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
         }
     }
 
-    private void startCheckConnectionJob(int accessibilityInterval, int aliveInterval) {
+    private void startCheckConnectionJob(int accessibilityInterval, int aliveInterval, boolean restartIfNoActivity) {
         ScheduledFuture<?> localCheckConnectionJob = checkConnectionJob;
         if (localCheckConnectionJob == null || localCheckConnectionJob.isCancelled()) {
             checkConnectionJob = scheduler.scheduleWithFixedDelay(() -> {
@@ -383,12 +386,12 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
                 if (getThing().getStatus() != ThingStatus.ONLINE || aliveInterval == 0
                         || restClient.getLastEventTimestamp() == 0) {
                     logger.debug("Time to check server accessibility");
-                    checkConnection();
+                    checkConnection(restartIfNoActivity && aliveInterval != 0);
                 } else if (millisSinceLastEvent > (aliveInterval * 60000)) {
                     logger.debug(
                             "Time to check server accessibility (maybe disconnected from streaming events, millisSinceLastEvent={})",
                             millisSinceLastEvent);
-                    checkConnection();
+                    checkConnection(restartIfNoActivity);
                 } else {
                     logger.debug(
                             "Bypass server accessibility check (receiving streaming events, millisSinceLastEvent={})",
index ebde376114ec6a719d3dfd52f5149f050da9a24a..a294e2215d2c34407f933e6ed31a6f8ef86dcac2 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.remoteopenhab.internal.rest;
 
 import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -21,6 +22,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 
 import javax.net.ssl.HostnameVerifier;
@@ -182,7 +184,7 @@ public class RemoteopenhabRestClient {
     public void sendCommandToRemoteItem(String itemName, Command command) throws RemoteopenhabException {
         try {
             String url = String.format("%s/%s", getRestApiUrl("items"), itemName);
-            executeUrl(HttpMethod.POST, url, "application/json", command.toFullString(), "text/plain", false);
+            executeUrl(HttpMethod.POST, url, "application/json", command.toFullString(), "text/plain", false, true);
         } catch (RemoteopenhabException e) {
             throw new RemoteopenhabException("Failed to send command to the remote item " + itemName
                     + " using the items REST API: " + e.getMessage(), e);
@@ -470,11 +472,11 @@ public class RemoteopenhabRestClient {
     }
 
     public String executeGetUrl(String url, String acceptHeader, boolean asyncReading) throws RemoteopenhabException {
-        return executeUrl(HttpMethod.GET, url, acceptHeader, null, null, asyncReading);
+        return executeUrl(HttpMethod.GET, url, acceptHeader, null, null, asyncReading, true);
     }
 
     public String executeUrl(HttpMethod httpMethod, String url, String acceptHeader, @Nullable String content,
-            @Nullable String contentType, boolean asyncReading) throws RemoteopenhabException {
+            @Nullable String contentType, boolean asyncReading, boolean retryIfEOF) throws RemoteopenhabException {
         final Request request = httpClient.newRequest(url).method(httpMethod).timeout(REQUEST_TIMEOUT,
                 TimeUnit.MILLISECONDS);
 
@@ -517,6 +519,16 @@ public class RemoteopenhabRestClient {
             }
         } catch (RemoteopenhabException e) {
             throw e;
+        } catch (ExecutionException e) {
+            // After a long network outage, the first HTTP request will fail with an EOFException exception.
+            // We retry the request a second time in this case.
+            Throwable cause = e.getCause();
+            if (retryIfEOF && cause instanceof EOFException) {
+                logger.debug("EOFException - retry the request");
+                return executeUrl(httpMethod, url, acceptHeader, content, contentType, asyncReading, false);
+            } else {
+                throw new RemoteopenhabException(e);
+            }
         } catch (Exception e) {
             throw new RemoteopenhabException(e);
         }
index 0f4d212d96bb9ad2418488fc0810130f0f3911f5..5d7c0fe6b003672a3564218e6dce33a003defd93 100644 (file)
 
                        <parameter name="aliveInterval" type="integer" min="0" step="1" unit="min">
                                <label>Alive Interval</label>
-                               <description>Number of last minutes to take into account to determine whether the remote server is alive. 0 to
-                                       disable this feature. Default is 5.</description>
+                               <description>Number of last minutes to consider when monitoring the receipt of events from the remote server. If an
+                                       event is received during this interval, the remote server is considered alive and its accessibility will not be
+                                       verified. Use 0 to disable this feature. Default is 5.</description>
                                <default>5</default>
                                <advanced>true</advanced>
                        </parameter>
+
+                       <parameter name="restartIfNoActivity" type="boolean">
+                               <label>Restart if no Activity</label>
+                               <description>Set it to true if you want to restart the connection (SSE) to the remote server when no events are
+                                       received in the monitored interval. It is not necessary if the goal is to properly handle a short network outage
+                                       (few seconds). This can be useful if you want to deal with a long network outage. Do not enable it if you remote
+                                       server does not send events during the monitored interval under normal conditions, it will cause frequent restart
+                                       of the connection and potential loss of events. Default is false.
+                               </description>
+                               <default>false</default>
+                               <advanced>true</advanced>
+                       </parameter>
                </config-description>
        </bridge-type>