From e03b6a03f421a61fa80e2857600627a94627a386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Sat, 28 Feb 2026 10:58:12 +0100 Subject: [PATCH] [netatmo] Enforce API reconnect delay (#18029) * Enable push / pull mode when webhook is set Signed-off-by: clinique Signed-off-by: gael@lhopital.org --- .../internal/api/data/NetatmoConstants.java | 2 + .../config/ApiHandlerConfiguration.java | 8 ++- .../internal/handler/ApiBridgeHandler.java | 65 +++++++++++++------ .../capability/AlarmEventCapability.java | 5 +- .../handler/capability/CameraCapability.java | 3 +- .../handler/capability/Capability.java | 25 +++---- .../HomeSecurityThingCapability.java | 11 ++-- .../handler/capability/PersonCapability.java | 14 ++-- .../capability/RefreshAutoCapability.java | 26 ++++---- .../handler/capability/RefreshCapability.java | 21 +++--- .../handler/capability/RestCapability.java | 2 +- .../handler/channelhelper/ChannelHelper.java | 6 ++ .../internal/servlet/NetatmoServlet.java | 7 +- .../internal/servlet/WebhookServlet.java | 3 +- .../resources/OH-INF/i18n/netatmo.properties | 1 + 15 files changed, 124 insertions(+), 75 deletions(-) diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java index adb677f80d..964630cc9f 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/api/data/NetatmoConstants.java @@ -420,6 +420,8 @@ public class NetatmoConstants { DEVICE_NOT_FOUND, @SerializedName("10") MISSING_ARGUMENTS, + @SerializedName("11") + CONCURRENCY_LIMIT_TIMED_OUT, @SerializedName("13") OPERATION_FORBIDDEN, @SerializedName("19") diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/ApiHandlerConfiguration.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/ApiHandlerConfiguration.java index 3436f75456..22c792aa91 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/ApiHandlerConfiguration.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/ApiHandlerConfiguration.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.netatmo.internal.config; +import java.time.Duration; + import org.eclipse.jdt.annotation.NonNullByDefault; /** @@ -28,7 +30,7 @@ public class ApiHandlerConfiguration { public String clientSecret = ""; public String webHookUrl = ""; public String webHookPostfix = ""; - public int reconnectInterval = 300; + private int reconnectInterval = 300; public ConfigurationLevel check() { if (clientId.isBlank()) { @@ -38,4 +40,8 @@ public class ApiHandlerConfiguration { } return ConfigurationLevel.COMPLETED; } + + public Duration getReconnectInterval() { + return Duration.ofSeconds(reconnectInterval); + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java index 570af000d7..8a158008e7 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/ApiBridgeHandler.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayDeque; @@ -161,6 +162,7 @@ public class ApiBridgeHandler extends BaseBridgeHandler { } logger.debug("Connected to Netatmo API."); + freeConnectJob(); ApiHandlerConfiguration configuration = getConfiguration(); if (!configuration.webHookUrl.isBlank() @@ -199,7 +201,11 @@ public class ApiBridgeHandler extends BaseBridgeHandler { startAuthorizationFlow(); return false; } catch (IOException e) { - prepareReconnection(getConfiguration().reconnectInterval, e.getMessage(), code, redirectUri); + String message = e.getMessage(); + if (message == null) { + message = e.getClass().getName(); + } + prepareReconnection(message, code, redirectUri); return false; } @@ -226,29 +232,32 @@ public class ApiBridgeHandler extends BaseBridgeHandler { return getConfigAs(ApiHandlerConfiguration.class); } - private void prepareReconnection(int delay, @Nullable String message, @Nullable String code, + private void prepareReconnection(String message, @Nullable String code, @Nullable String redirectUri) { + prepareReconnection(message, getConfiguration().getReconnectInterval(), code, redirectUri); + } + + private void prepareReconnection(String message, Duration delay, @Nullable String code, @Nullable String redirectUri) { if (!ThingStatus.OFFLINE.equals(thing.getStatus())) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Reconnection in %s: %s".formatted(delay, message)); } connectApi.dispose(); freeConnectJob(); - connectJob = scheduler.schedule(() -> openConnection(code, redirectUri), delay, TimeUnit.SECONDS); + connectJob = scheduler.schedule(() -> openConnection(code, redirectUri), delay.toSeconds(), TimeUnit.SECONDS); logger.debug("Reconnection scheduled in {} seconds", delay); } private void freeConnectJob() { - ScheduledFuture connectJob = this.connectJob; - if (connectJob != null) { - connectJob.cancel(true); + if (connectJob instanceof ScheduledFuture job) { + job.cancel(true); } this.connectJob = null; } private void freeGrantServlet() { - GrantServlet grantServlet = this.grantServlet; - if (grantServlet != null) { - grantServlet.dispose(); + if (grantServlet instanceof GrantServlet servlet) { + servlet.dispose(); } this.grantServlet = null; } @@ -304,13 +313,17 @@ public class ApiBridgeHandler extends BaseBridgeHandler { public synchronized T executeUri(URI uri, HttpMethod method, Class clazz, @Nullable String payload, @Nullable String contentType, int retryCount) throws NetatmoException { + if (connectJob != null) { + throw new NetatmoException("Connection pending, no other request accepted in the meantime."); + } + + logger.debug("executeUri {} {} ", method.toString(), uri); + + Request request = httpClient.newRequest(uri).method(method).timeout(TIMEOUT_S, TimeUnit.SECONDS); + try { - logger.debug("executeUri {} {} ", method.toString(), uri); - - Request request = httpClient.newRequest(uri).method(method).timeout(TIMEOUT_S, TimeUnit.SECONDS); - if (!authenticate(null, null)) { - prepareReconnection(getConfiguration().reconnectInterval, "@text/status-bridge-offline", null, null); + prepareReconnection("@text/status-bridge-offline", null, null); throw new NetatmoException("Not authenticated"); } connectApi.getAuthorization().ifPresent(auth -> request.header(HttpHeader.AUTHORIZATION, auth)); @@ -359,10 +372,18 @@ public class ApiBridgeHandler extends BaseBridgeHandler { "Error deserializing error: %s".formatted(statusCode.getMessage())); } } - if (statusCode == Code.TOO_MANY_REQUESTS - || exception.getStatusCode() == ServiceError.MAXIMUM_USAGE_REACHED) { - prepareReconnection(API_LIMIT_INTERVAL_S, - "@text/maximum-usage-reached [ \"%d\" ]".formatted(API_LIMIT_INTERVAL_S), null, null); + if (statusCode == Code.TOO_MANY_REQUESTS) { + String message = null; + String delayStr = response.getHeaders().get(HttpHeader.RETRY_AFTER); + int delay = delayStr != null ? Integer.valueOf(delayStr) : Integer.MAX_VALUE; + if (exception.getStatusCode() == ServiceError.CONCURRENCY_LIMIT_TIMED_OUT) { + delay = Math.min(delay, TIMEOUT_S); + message = "@text/concurrency-limit-timed-out [ \"%d\" ]"; + } else { // ServiceError.MAXIMUM_USAGE_REACHED + delay = Math.min(delay, API_LIMIT_INTERVAL_S); + message = "@text/maximum-usage-reached [ \"%d\" ]"; + } + prepareReconnection(message.formatted(delay), Duration.ofSeconds(delay), null, null); } throw exception; } catch (InterruptedException e) { @@ -374,7 +395,7 @@ public class ApiBridgeHandler extends BaseBridgeHandler { logger.debug("Request error, retry counter: {}", retryCount); return executeUri(uri, method, clazz, payload, contentType, retryCount - 1); } - prepareReconnection(getConfiguration().reconnectInterval, "@text/request-time-out", null, e.getMessage()); + prepareReconnection("@text/request-time-out", null, e.getMessage()); throw new NetatmoException("%s: \"%s\"".formatted(e.getClass().getName(), e.getMessage())); } } @@ -463,4 +484,8 @@ public class ApiBridgeHandler extends BaseBridgeHandler { public Optional getWebHookServlet() { return Optional.ofNullable(webHookServlet); } + + public @Nullable Duration getIdleTime() { + return connectJob instanceof ScheduledFuture job ? Duration.ofSeconds(job.getDelay(TimeUnit.SECONDS)) : null; + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/AlarmEventCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/AlarmEventCapability.java index 41ea608fc8..8fd49775db 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/AlarmEventCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/AlarmEventCapability.java @@ -55,8 +55,9 @@ public class AlarmEventCapability extends HomeSecurityThingCapability { @Override public List updateReadings() { - return Objects.requireNonNull( + return pullMode() ? Objects.requireNonNull( getSecurityCapability().map(cap -> cap.getDeviceLastEvent(handler.getId(), moduleType.apiName)) - .map(event -> List.of((NAObject) event)).orElse(List.of())); + .map(event -> List.of((NAObject) event)).orElse(List.of())) + : List.of(); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java index 0a06cbf715..93d56ce56e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/CameraCapability.java @@ -99,8 +99,7 @@ public class CameraCapability extends HomeSecurityThingCapability { vpnUrl = newVpnUrl; if (!SdCardStatus.SD_CARD_WORKING.equals(newData.getSdStatus())) { statusReason = newData.getSdStatus().toString(); - } - if (!AlimentationStatus.ALIM_CORRECT_POWER.equals(newData.getAlimStatus())) { + } else if (!AlimentationStatus.ALIM_CORRECT_POWER.equals(newData.getAlimStatus())) { statusReason = newData.getAlimStatus().toString(); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java index 20e6355c46..bc6827f7af 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/Capability.java @@ -105,46 +105,46 @@ public class Capability { statusReason = null; } - protected void afterNewData(@Nullable NAObject newData) { + protected void afterNewData(@SuppressWarnings("unused") @Nullable NAObject newData) { if (!properties.equals(getThing().getProperties())) { getThing().setProperties(properties); } firstLaunch = false; } - protected void updateNAThing(NAThing newData) { + protected void updateNAThing(@SuppressWarnings("unused") NAThing newData) { // do nothing by default, can be overridden by subclasses } - protected void updateNAMain(NAMain newData) { + protected void updateNAMain(@SuppressWarnings("unused") NAMain newData) { // do nothing by default, can be overridden by subclasses } - protected void updateHomeEvent(HomeEvent newData) { + protected void updateHomeEvent(@SuppressWarnings("unused") HomeEvent newData) { // do nothing by default, can be overridden by subclasses } - protected void updateHomeStatus(HomeStatus newData) { + protected void updateHomeStatus(@SuppressWarnings("unused") HomeStatus newData) { // do nothing by default, can be overridden by subclasses } - protected void updateHomeData(HomeData newData) { + protected void updateHomeData(@SuppressWarnings("unused") HomeData newData) { // do nothing by default, can be overridden by subclasses } - protected void updateEvent(Event newData) { + protected void updateEvent(@SuppressWarnings("unused") Event newData) { // do nothing by default, can be overridden by subclasses } - protected void updateWebhookEvent(WebhookEvent newData) { + protected void updateWebhookEvent(@SuppressWarnings("unused") WebhookEvent newData) { // do nothing by default, can be overridden by subclasses } - protected void updateNADevice(Device newData) { + protected void updateNADevice(@SuppressWarnings("unused") Device newData) { // do nothing by default, can be overridden by subclasses } - protected void updateErrors(NAError error) { + protected void updateErrors(@SuppressWarnings("unused") NAError error) { // do nothing by default, can be overridden by subclasses } @@ -163,11 +163,12 @@ public class Capability { // do nothing by default, can be overridden by subclasses } - public void updateHomeStatusModule(HomeStatusModule newData) { + public void updateHomeStatusModule(@SuppressWarnings("unused") HomeStatusModule newData) { // do nothing by default, can be overridden by subclasses } - public void handleCommand(String channelName, Command command) { + public void handleCommand(@SuppressWarnings("unused") String channelName, + @SuppressWarnings("unused") Command command) { // do nothing by default, can be overridden by subclasses } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java index 4e92782403..f39d4bd8b8 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeSecurityThingCapability.java @@ -53,8 +53,7 @@ public abstract class HomeSecurityThingCapability extends Capability { protected Optional getSecurityCapability() { if (securityCapability == null) { handler.getHomeCapability(SecurityCapability.class).ifPresent(cap -> securityCapability = cap); - ApiBridgeHandler accountHandler = handler.getAccountHandler(); - if (accountHandler != null) { + if (handler.getAccountHandler() instanceof ApiBridgeHandler accountHandler) { webhookServlet = null; accountHandler.getWebHookServlet().ifPresent(servlet -> { webhookServlet = servlet; @@ -74,10 +73,14 @@ public abstract class HomeSecurityThingCapability extends Capability { @Override public void dispose() { - WebhookServlet webhook = this.webhookServlet; - if (webhook != null) { + if (webhookServlet instanceof WebhookServlet webhook) { webhook.unregisterDataListener(handler.getId()); + webhookServlet = null; } super.dispose(); } + + protected boolean pullMode() { + return webhookServlet == null; + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java index e6e6687f91..ef159cbebb 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PersonCapability.java @@ -106,12 +106,14 @@ public class PersonCapability extends HomeSecurityThingCapability { @Override public List updateReadings() { List result = new ArrayList<>(); - getSecurityCapability().ifPresent(cap -> { - HomeEvent event = cap.getLastPersonEvent(handler.getId()); - if (event != null) { - result.add(event); - } - }); + if (pullMode()) { + getSecurityCapability().ifPresent(cap -> { + HomeEvent event = cap.getLastPersonEvent(handler.getId()); + if (event != null) { + result.add(event); + } + }); + } return result; } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshAutoCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshAutoCapability.java index 6d6a1b7210..360bee2e85 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshAutoCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshAutoCapability.java @@ -36,7 +36,7 @@ public class RefreshAutoCapability extends RefreshCapability { private final Logger logger = LoggerFactory.getLogger(RefreshAutoCapability.class); - private Instant dataTimeStamp = Instant.MIN; + private @Nullable Instant dataTimestamp = null; public RefreshAutoCapability(CommonInterface handler) { super(handler); @@ -44,38 +44,38 @@ public class RefreshAutoCapability extends RefreshCapability { @Override public void expireData() { - dataTimeStamp = Instant.MIN; + dataTimestamp = null; super.expireData(); } @Override protected Duration calcDelay() { - if (Instant.MIN.equals(dataTimeStamp)) { + Instant timestamp = dataTimestamp; + if (timestamp == null) { return PROBING_INTERVAL; } - Duration dataAge = Duration.between(dataTimeStamp, Instant.now()); - + Duration dataAge = Duration.between(timestamp, Instant.now()); Duration delay = dataValidity.minus(dataAge); - if (delay.isNegative() || delay.isZero()) { - logger.debug("{} did not update data in expected time, return to probing", thingUID); - dataTimeStamp = Instant.MIN; - return PROBING_INTERVAL; + + if (delay.isPositive()) { + return delay.plus(DEFAULT_DELAY); } - return delay.plus(DEFAULT_DELAY); + logger.debug("{} did not update data in expected time, return to probing", thingUID); + dataTimestamp = null; + return PROBING_INTERVAL; } @Override protected void updateNAThing(NAThing newData) { super.updateNAThing(newData); - ZonedDateTime lastSeen = newData.getLastSeen(); - dataTimeStamp = lastSeen != null ? lastSeen.toInstant() : Instant.MIN; + dataTimestamp = newData.getLastSeen() instanceof ZonedDateTime ls ? ls.toInstant() : null; } @Override protected void afterNewData(@Nullable NAObject newData) { - properties.put("probing", Boolean.valueOf(Instant.MIN.equals(dataTimeStamp)).toString()); + properties.put("probing", Boolean.valueOf(dataTimestamp == null).toString()); super.afterNewData(newData); } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshCapability.java index 16eddb010d..0c7aed2537 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RefreshCapability.java @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.netatmo.internal.api.dto.NAObject; +import org.openhab.binding.netatmo.internal.handler.ApiBridgeHandler; import org.openhab.binding.netatmo.internal.handler.CommonInterface; import org.openhab.core.thing.ThingStatus; import org.slf4j.Logger; @@ -35,7 +36,7 @@ import org.slf4j.LoggerFactory; */ @NonNullByDefault public class RefreshCapability extends Capability { - protected static final Duration ASAP = Duration.ofSeconds(2); + public static final Duration ASAP = Duration.ofSeconds(2); protected static final Duration OFFLINE_DELAY = Duration.ofMinutes(15); protected static final Duration PROBING_INTERVAL = Duration.ofMinutes(2); @@ -50,7 +51,7 @@ public class RefreshCapability extends Capability { } public void setInterval(Duration dataValidity) { - if (dataValidity.isNegative() || dataValidity.isZero()) { + if (!dataValidity.isPositive()) { throw new IllegalArgumentException("refreshInterval must be positive"); } this.dataValidity = dataValidity; @@ -84,9 +85,14 @@ public class RefreshCapability extends Capability { private void proceedWithUpdate() { Duration delay; handler.proceedWithUpdate(); - if (!ThingStatus.ONLINE.equals(handler.getThing().getStatus())) { + if (handler.getAccountHandler() instanceof ApiBridgeHandler accountHandler + && !ThingStatus.ONLINE.equals(accountHandler.getThing().getStatus())) { + delay = accountHandler.getIdleTime(); + delay = delay != null ? delay.plus(ASAP) : OFFLINE_DELAY; + logger.debug("Bridge is not ONLINE, will wait for him to come-back in {}", delay); + } else if (!ThingStatus.ONLINE.equals(handler.getThing().getStatus())) { delay = OFFLINE_DELAY; - logger.debug("Thing '{}' is not ONLINE, using special refresh interval", thingUID); + logger.debug("Thing '{}' is not ONLINE, special refresh interval {} used", thingUID, delay); } else { delay = calcDelay(); } @@ -110,10 +116,9 @@ public class RefreshCapability extends Capability { } private void stopJob() { - ScheduledFuture refreshJob = this.refreshJob; - if (refreshJob != null) { - refreshJob.cancel(true); + if (refreshJob instanceof ScheduledFuture job) { + job.cancel(true); } - this.refreshJob = null; + refreshJob = null; } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RestCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RestCapability.java index 6d13f8566a..ab39cc1059 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RestCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/RestCapability.java @@ -61,7 +61,7 @@ public abstract class RestCapability extends DeviceCapabi return result; } - protected List updateReadings(T api) { + protected List updateReadings(@SuppressWarnings("unused") T api) { return List.of(); } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/ChannelHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/ChannelHelper.java index ab3ccf3125..bd7048fd80 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/ChannelHelper.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/channelhelper/ChannelHelper.java @@ -84,26 +84,32 @@ public abstract class ChannelHelper { return result; } + @SuppressWarnings("unused") protected @Nullable State internalGetObject(String channelId, NAObject localData) { return null; } + @SuppressWarnings("unused") protected @Nullable State internalGetOther(String channelId) { return null; } + @SuppressWarnings("unused") protected @Nullable State internalGetDashboard(String channelId, Dashboard dashboard) { return null; } + @SuppressWarnings("unused") protected @Nullable State internalGetProperty(String channelId, NAThing naThing, Configuration config) { return null; } + @SuppressWarnings("unused") protected @Nullable State internalGetEvent(String channelId, Event event) { return null; } + @SuppressWarnings("unused") protected @Nullable State internalGetHomeEvent(String channelId, @Nullable String groupId, HomeEvent event) { return null; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/NetatmoServlet.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/NetatmoServlet.java index e6ff399933..794cf6deaf 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/NetatmoServlet.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/NetatmoServlet.java @@ -32,18 +32,17 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public abstract class NetatmoServlet extends HttpServlet { private static final long serialVersionUID = 5671438863935117735L; - private static final String BASE_PATH = "/" + BINDING_ID + "/"; - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final Logger logger = LoggerFactory.getLogger(NetatmoServlet.class); private final HttpService httpService; private final String path; protected final ApiBridgeHandler handler; public NetatmoServlet(ApiBridgeHandler handler, HttpService httpService, String localPath) { - this.path = BASE_PATH + localPath + "/" + handler.getId(); - this.handler = handler; + this.path = "/" + BINDING_ID + "/" + localPath + "/" + handler.getId(); this.httpService = httpService; + this.handler = handler; } public void startListening() { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java index 4aa84a45d6..a5e187776c 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/servlet/WebhookServlet.java @@ -121,8 +121,7 @@ public class WebhookServlet extends NetatmoServlet { private void notifyListeners(WebhookEvent event) { event.getNAObjectList().forEach(id -> { - Capability module = dataListeners.get(id); - if (module != null) { + if (dataListeners.get(id) instanceof Capability module) { logger.trace("Dispatching webhook event to {}", id); module.setNewData(event); } diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties index a1f5bbb6b3..0b08c87ac1 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/OH-INF/i18n/netatmo.properties @@ -500,6 +500,7 @@ data-over-limit = Data seems quite old request-time-out = Request timed out - will attempt reconnection later deserialization-unknown = Deserialization lead to an unknown code maximum-usage-reached = Maximum usage reached, will reconnect in {0} seconds. +concurrency-limit-timed-out = Concurrency limited section, will retry in {0} seconds. homestatus-unknown-error = Unknown error homestatus-internal-error = Internal error homestatus-parser-error = Parser error