diff --git a/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java b/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java index 8a7ae3efd49..12fc672d6e7 100644 --- a/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java +++ b/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/api/MeaterRestAPI.java @@ -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 meaterProbeThings) { - try { - MeaterProbeDTO dto = getDevices(MeaterProbeDTO.class); - if (dto != null) { - List 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 meaterProbeThings) throws MeaterException { + MeaterProbeDTO dto = getDevices(MeaterProbeDTO.class); + if (dto != null) { + List 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); diff --git a/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/handler/MeaterBridgeHandler.java b/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/handler/MeaterBridgeHandler.java index 509e6b08d8c..d7dc24ae13d 100644 --- a/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/handler/MeaterBridgeHandler.java +++ b/bundles/org.openhab.binding.meater/src/main/java/org/openhab/binding/meater/internal/handler/MeaterBridgeHandler.java @@ -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.i18n.TranslationProvider; import org.openhab.core.thing.Bridge; @@ -109,23 +110,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() {