]> git.basschouten.com Git - openhab-addons.git/commitdiff
[remoteopenhab] Asynchronous reading of big API response (#9320)
authorlolodomo <lg.hc@free.fr>
Fri, 11 Dec 2020 22:48:00 +0000 (23:48 +0100)
committerGitHub <noreply@github.com>
Fri, 11 Dec 2020 22:48:00 +0000 (14:48 -0800)
* [remoteopenhab] Asynchronous reading of big API response

Fix #9281

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
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

index 06040dfaf0bf3c015704fc134b50a849c149c68a..97dfbd957465e6d47e4813a84e9626a52f4ada12 100644 (file)
@@ -331,18 +331,12 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
                         "OH 1.x server not supported by the binding");
             } else if (getThing().getStatus() != ThingStatus.ONLINE) {
-                List<RemoteopenhabItem> items = restClient.getRemoteItems("name,type,groupType,stateDescription");
+                List<RemoteopenhabItem> items = restClient.getRemoteItems("name,type,groupType,state,stateDescription");
 
                 createChannels(items, true);
                 setStateOptions(items);
-
-                try {
-                    items = restClient.getRemoteItems("name,state");
-                    for (RemoteopenhabItem item : items) {
-                        updateChannelState(item.name, null, item.state, false);
-                    }
-                } catch (RemoteopenhabException e) {
-                    logger.debug("{}", e.getMessage());
+                for (RemoteopenhabItem item : items) {
+                    updateChannelState(item.name, null, item.state, false);
                 }
 
                 updateStatus(ThingStatus.ONLINE);
index fc6e4a5de28cd07c84946b6f11a81df078af6a98..fab3d7cf3edabb74ab4c608765cd96e06e5710f6 100644 (file)
@@ -13,6 +13,7 @@
 package org.openhab.binding.remoteopenhab.internal.rest;
 
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
@@ -37,7 +38,9 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
 import org.eclipse.jetty.client.api.ContentResponse;
 import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
 import org.eclipse.jetty.client.util.InputStreamContentProvider;
+import org.eclipse.jetty.client.util.InputStreamResponseListener;
 import org.eclipse.jetty.http.HttpMethod;
 import org.eclipse.jetty.http.HttpStatus;
 import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabChannelTriggerEvent;
@@ -128,7 +131,7 @@ public class RemoteopenhabRestClient {
 
     public void tryApi() throws RemoteopenhabException {
         try {
-            String jsonResponse = executeUrl(HttpMethod.GET, getRestUrl(), "application/json", null, null);
+            String jsonResponse = executeGetUrl(getRestUrl(), "application/json", false);
             if (jsonResponse.isEmpty()) {
                 throw new RemoteopenhabException("JSON response is empty");
             }
@@ -155,7 +158,8 @@ public class RemoteopenhabRestClient {
             if (fields != null) {
                 url += "&fields=" + fields;
             }
-            String jsonResponse = executeUrl(HttpMethod.GET, url, "application/json", null, null);
+            boolean asyncReading = fields == null || Arrays.asList(fields.split(",")).contains("state");
+            String jsonResponse = executeGetUrl(url, "application/json", asyncReading);
             if (jsonResponse.isEmpty()) {
                 throw new RemoteopenhabException("JSON response is empty");
             }
@@ -169,7 +173,7 @@ public class RemoteopenhabRestClient {
     public String getRemoteItemState(String itemName) throws RemoteopenhabException {
         try {
             String url = String.format("%s/%s/state", getRestApiUrl("items"), itemName);
-            return executeUrl(HttpMethod.GET, url, "text/plain", null, null);
+            return executeGetUrl(url, "text/plain", true);
         } catch (RemoteopenhabException e) {
             throw new RemoteopenhabException("Failed to get the state of remote item " + itemName
                     + " using the items REST API: " + e.getMessage(), e);
@@ -180,7 +184,7 @@ public class RemoteopenhabRestClient {
         try {
             String url = String.format("%s/%s", getRestApiUrl("items"), itemName);
             InputStream stream = new ByteArrayInputStream(command.toFullString().getBytes(StandardCharsets.UTF_8));
-            executeUrl(HttpMethod.POST, url, "application/json", stream, "text/plain");
+            executeUrl(HttpMethod.POST, url, "application/json", stream, "text/plain", false);
             stream.close();
         } catch (RemoteopenhabException | IOException e) {
             throw new RemoteopenhabException("Failed to send command to the remote item " + itemName
@@ -190,7 +194,7 @@ public class RemoteopenhabRestClient {
 
     public List<RemoteopenhabThing> getRemoteThings() throws RemoteopenhabException {
         try {
-            String jsonResponse = executeUrl(HttpMethod.GET, getRestApiUrl("things"), "application/json", null, null);
+            String jsonResponse = executeGetUrl(getRestApiUrl("things"), "application/json", false);
             if (jsonResponse.isEmpty()) {
                 throw new RemoteopenhabException("JSON response is empty");
             }
@@ -204,7 +208,7 @@ public class RemoteopenhabRestClient {
     public RemoteopenhabThing getRemoteThing(String uid) throws RemoteopenhabException {
         try {
             String url = String.format("%s/%s", getRestApiUrl("things"), uid);
-            String jsonResponse = executeUrl(HttpMethod.GET, url, "application/json", null, null);
+            String jsonResponse = executeGetUrl(url, "application/json", false);
             if (jsonResponse.isEmpty()) {
                 throw new RemoteopenhabException("JSON response is empty");
             }
@@ -462,8 +466,12 @@ public class RemoteopenhabRestClient {
         return parts[2];
     }
 
+    public String executeGetUrl(String url, String acceptHeader, boolean asyncReading) throws RemoteopenhabException {
+        return executeUrl(HttpMethod.GET, url, acceptHeader, null, null, asyncReading);
+    }
+
     public String executeUrl(HttpMethod httpMethod, String url, String acceptHeader, @Nullable InputStream content,
-            @Nullable String contentType) throws RemoteopenhabException {
+            @Nullable String contentType, boolean asyncReading) throws RemoteopenhabException {
         final Request request = httpClient.newRequest(url).method(httpMethod).timeout(REQUEST_TIMEOUT,
                 TimeUnit.MILLISECONDS);
 
@@ -481,15 +489,34 @@ public class RemoteopenhabRestClient {
         }
 
         try {
-            ContentResponse response = request.send();
-            int statusCode = response.getStatus();
-            if (statusCode >= HttpStatus.BAD_REQUEST_400) {
-                String statusLine = statusCode + " " + response.getReason();
-                throw new RemoteopenhabException("HTTP call failed: " + statusLine);
+            if (asyncReading) {
+                InputStreamResponseListener listener = new InputStreamResponseListener();
+                request.send(listener);
+                Response response = listener.get(5, TimeUnit.SECONDS);
+                int statusCode = response.getStatus();
+                if (statusCode != HttpStatus.OK_200) {
+                    response.abort(new Exception(response.getReason()));
+                    String statusLine = statusCode + " " + response.getReason();
+                    throw new RemoteopenhabException("HTTP call failed: " + statusLine);
+                }
+                ByteArrayOutputStream responseContent = new ByteArrayOutputStream();
+                try (InputStream input = listener.getInputStream()) {
+                    input.transferTo(responseContent);
+                }
+                return new String(responseContent.toByteArray(), StandardCharsets.UTF_8.name());
+            } else {
+                ContentResponse response = request.send();
+                int statusCode = response.getStatus();
+                if (statusCode >= HttpStatus.BAD_REQUEST_400) {
+                    String statusLine = statusCode + " " + response.getReason();
+                    throw new RemoteopenhabException("HTTP call failed: " + statusLine);
+                }
+                String encoding = response.getEncoding() != null ? response.getEncoding().replaceAll("\"", "").trim()
+                        : StandardCharsets.UTF_8.name();
+                return new String(response.getContent(), encoding);
             }
-            String encoding = response.getEncoding() != null ? response.getEncoding().replaceAll("\"", "").trim()
-                    : StandardCharsets.UTF_8.name();
-            return new String(response.getContent(), encoding);
+        } catch (RemoteopenhabException e) {
+            throw e;
         } catch (Exception e) {
             throw new RemoteopenhabException(e);
         }