]> git.basschouten.com Git - openhab-addons.git/commitdiff
[meater] Fix broken cloud communication (#16994)
authorJacob Laursen <jacob-github@vindvejr.dk>
Fri, 5 Jul 2024 14:55:05 +0000 (16:55 +0200)
committerGitHub <noreply@github.com>
Fri, 5 Jul 2024 14:55:05 +0000 (16:55 +0200)
* Improve error handling

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java
bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/handler/MeaterBridgeHandler.java

index de6694b079af05a4d2c40a0c062fb7356c5cc6c8..539d81a9a3de22e436fcba565fc0a60f66a58c16 100644 (file)
@@ -35,6 +35,7 @@ import org.openhab.binding.meater.internal.dto.MeaterProbeDTO.Device;
 import org.openhab.binding.meater.internal.exceptions.MeaterAuthenticationException;
 import org.openhab.binding.meater.internal.exceptions.MeaterException;
 import org.openhab.core.i18n.LocaleProvider;
+import org.osgi.framework.FrameworkUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,6 +64,7 @@ public class MeaterRestAPI {
     private final Gson gson;
     private final HttpClient httpClient;
     private final MeaterBridgeConfiguration configuration;
+    private final String userAgent;
     private String authToken = "";
     private LocaleProvider localeProvider;
 
@@ -72,42 +74,42 @@ public class MeaterRestAPI {
         this.configuration = configuration;
         this.httpClient = httpClient;
         this.localeProvider = localeProvider;
+        userAgent = "openHAB/" + FrameworkUtil.getBundle(this.getClass()).getVersion().toString();
     }
 
-    public boolean refresh(Map<String, MeaterProbeDTO.Device> meaterProbeThings) {
-        try {
-            MeaterProbeDTO dto = getDevices(MeaterProbeDTO.class);
-            if (dto != null) {
-                List<Device> devices = dto.getData().getDevices();
-                if (devices != null) {
-                    if (!devices.isEmpty()) {
-                        for (Device meaterProbe : devices) {
-                            meaterProbeThings.put(meaterProbe.id, meaterProbe);
-                        }
-                    } else {
-                        meaterProbeThings.clear();
+    public void refresh(Map<String, MeaterProbeDTO.Device> meaterProbeThings) throws MeaterException {
+        MeaterProbeDTO dto = getDevices(MeaterProbeDTO.class);
+        if (dto != null) {
+            List<Device> devices = dto.getData().getDevices();
+            if (devices != null) {
+                if (!devices.isEmpty()) {
+                    for (Device meaterProbe : devices) {
+                        meaterProbeThings.put(meaterProbe.id, meaterProbe);
                     }
-                    return true;
+                } else {
+                    meaterProbeThings.clear();
                 }
             }
-        } catch (MeaterException e) {
-            logger.warn("Failed to refresh! {}", e.getMessage());
         }
-        return false;
     }
 
     private void login() throws MeaterException {
         try {
             // Login
-            String json = "{ \"email\": \"" + configuration.email + "\",  \"password\": \"" + configuration.password
-                    + "\" }";
-            Request request = httpClient.newRequest(API_ENDPOINT + LOGIN).method(HttpMethod.POST)
-                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
-            request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
-            request.content(new StringContentProvider(json), JSON_CONTENT_TYPE);
+            String json = """
+                    {
+                        "email": "%s",
+                        "password": "%s"
+                    }
+                    """.formatted(configuration.email, configuration.password);
+            Request request = httpClient.newRequest(API_ENDPOINT + LOGIN) //
+                    .method(HttpMethod.POST) //
+                    .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS) //
+                    .header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE) //
+                    .agent(userAgent) //
+                    .content(new StringContentProvider(json), JSON_CONTENT_TYPE);
 
-            logger.trace("{}.", request.toString());
+            logger.trace("{}", request.toString());
 
             ContentResponse httpResponse = request.send();
             if (!HttpStatus.isSuccess(httpResponse.getStatus())) {
@@ -135,24 +137,25 @@ public class MeaterRestAPI {
         try {
             for (int i = 0; i < MAX_RETRIES; i++) {
                 try {
-                    Request request = httpClient.newRequest(API_ENDPOINT + uri).method(HttpMethod.GET)
-                            .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-                    request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
-                    request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
-                    request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
-                    request.header(HttpHeader.ACCEPT_LANGUAGE, localeProvider.getLocale().getLanguage());
+                    Request request = httpClient.newRequest(API_ENDPOINT + uri) //
+                            .method(HttpMethod.GET) //
+                            .timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
+                            .header(HttpHeader.AUTHORIZATION, "Bearer " + authToken)
+                            .header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE)
+                            .header(HttpHeader.ACCEPT_LANGUAGE, localeProvider.getLocale().getLanguage())
+                            .agent(userAgent);
 
                     ContentResponse response = request.send();
                     String content = response.getContentAsString();
                     logger.trace("API response: {}", content);
 
-                    if (response.getStatus() == HttpStatus.UNAUTHORIZED_401) {
+                    int status = response.getStatus();
+                    if (status == HttpStatus.UNAUTHORIZED_401) {
                         // This will currently not happen because "WWW-Authenticate" header is missing; see below.
                         logger.debug("getFromApi failed, authentication failed, HTTP status: 401");
                         throw new MeaterAuthenticationException("Authentication failed");
-                    } else if (!HttpStatus.isSuccess(response.getStatus())) {
-                        logger.debug("getFromApi failed, HTTP status: {}", response.getStatus());
-                        throw new MeaterException("Failed to fetch from API!");
+                    } else if (!HttpStatus.isSuccess(status)) {
+                        throw new MeaterException(HttpStatus.getCode(status).getMessage());
                     } else {
                         return content;
                     }
@@ -160,7 +163,7 @@ public class MeaterRestAPI {
                     logger.debug("TimeoutException error in get: {}", e.getMessage());
                 }
             }
-            throw new MeaterException("Failed to fetch from API!");
+            throw new MeaterException("Failed to fetch from API");
         } catch (ExecutionException e) {
             Throwable cause = e.getCause();
             if (cause instanceof HttpResponseException httpResponseException) {
@@ -201,7 +204,7 @@ public class MeaterRestAPI {
         }
 
         if (json.isEmpty()) {
-            throw new MeaterException("JSON from API is empty!");
+            throw new MeaterException("JSON from API is empty");
         } else {
             try {
                 return gson.fromJson(json, dto);
index d05ab94af195314d944064de5411fe33a1adad7c..b9591e3a0d401668e0347ad087cc5565835f0473 100644 (file)
@@ -28,6 +28,7 @@ import org.openhab.binding.meater.internal.MeaterBridgeConfiguration;
 import org.openhab.binding.meater.internal.api.MeaterRestAPI;
 import org.openhab.binding.meater.internal.discovery.MeaterDiscoveryService;
 import org.openhab.binding.meater.internal.dto.MeaterProbeDTO;
+import org.openhab.binding.meater.internal.exceptions.MeaterException;
 import org.openhab.core.i18n.LocaleProvider;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.ChannelUID;
@@ -105,23 +106,24 @@ public class MeaterBridgeHandler extends BaseBridgeHandler {
         meaterProbeThings.clear();
     }
 
-    private boolean refreshAndUpdateStatus() {
+    private void refreshAndUpdateStatus() {
         MeaterRestAPI localAPI = api;
-        if (localAPI != null) {
-            if (localAPI.refresh(meaterProbeThings)) {
-                updateStatus(ThingStatus.ONLINE);
-                getThing().getThings().stream().forEach(thing -> {
-                    MeaterHandler handler = (MeaterHandler) thing.getHandler();
-                    if (handler != null) {
-                        handler.update();
-                    }
-                });
-                return true;
-            } else {
-                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
-            }
+        if (localAPI == null) {
+            return;
+        }
+
+        try {
+            localAPI.refresh(meaterProbeThings);
+            updateStatus(ThingStatus.ONLINE);
+            getThing().getThings().stream().forEach(thing -> {
+                MeaterHandler handler = (MeaterHandler) thing.getHandler();
+                if (handler != null) {
+                    handler.update();
+                }
+            });
+        } catch (MeaterException e) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
         }
-        return false;
     }
 
     private void startAutomaticRefresh() {