[netatmo] Ensure to close all scheduled jobs (#16056)
* Close all jobs --------- Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
5a70137e7b
commit
7a1884d4d1
@ -359,7 +359,7 @@ public class ApiBridgeHandler extends BaseBridgeHandler {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||||
throw new NetatmoException(String.format("%s: \"%s\"", e.getClass().getName(), e.getMessage()));
|
throw new NetatmoException("Request interrupted");
|
||||||
} catch (TimeoutException | ExecutionException e) {
|
} catch (TimeoutException | ExecutionException e) {
|
||||||
if (retryCount > 0) {
|
if (retryCount > 0) {
|
||||||
logger.debug("Request timedout, retry counter: {}", retryCount);
|
logger.debug("Request timedout, retry counter: {}", retryCount);
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
@ -30,6 +29,7 @@ import org.openhab.binding.netatmo.internal.config.NAThingConfiguration;
|
|||||||
import org.openhab.binding.netatmo.internal.handler.capability.Capability;
|
import org.openhab.binding.netatmo.internal.handler.capability.Capability;
|
||||||
import org.openhab.binding.netatmo.internal.handler.capability.CapabilityMap;
|
import org.openhab.binding.netatmo.internal.handler.capability.CapabilityMap;
|
||||||
import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability;
|
import org.openhab.binding.netatmo.internal.handler.capability.HomeCapability;
|
||||||
|
import org.openhab.binding.netatmo.internal.handler.capability.ParentUpdateCapability;
|
||||||
import org.openhab.binding.netatmo.internal.handler.capability.RefreshCapability;
|
import org.openhab.binding.netatmo.internal.handler.capability.RefreshCapability;
|
||||||
import org.openhab.binding.netatmo.internal.handler.capability.RestCapability;
|
import org.openhab.binding.netatmo.internal.handler.capability.RestCapability;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
@ -220,16 +220,15 @@ public interface CommonInterface {
|
|||||||
setThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED, null);
|
setThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED, null);
|
||||||
} else if (!ThingStatus.ONLINE.equals(bridge.getStatus())) {
|
} else if (!ThingStatus.ONLINE.equals(bridge.getStatus())) {
|
||||||
setThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null);
|
setThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null);
|
||||||
removeRefreshCapability();
|
getCapabilities().remove(RefreshCapability.class);
|
||||||
|
getCapabilities().remove(ParentUpdateCapability.class);
|
||||||
} else {
|
} else {
|
||||||
setThingStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, null);
|
setThingStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, null);
|
||||||
setRefreshCapability();
|
if (ModuleType.ACCOUNT.equals(getModuleType().getBridge())) {
|
||||||
getScheduler().schedule(() -> {
|
NAThingConfiguration config = getThing().getConfiguration().as(NAThingConfiguration.class);
|
||||||
CommonInterface bridgeHandler = getBridgeHandler();
|
getCapabilities().put(new RefreshCapability(this, config.refreshInterval));
|
||||||
if (bridgeHandler != null) {
|
|
||||||
bridgeHandler.expireData();
|
|
||||||
}
|
}
|
||||||
}, 1, TimeUnit.SECONDS);
|
getCapabilities().put(new ParentUpdateCapability(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,20 +236,6 @@ public interface CommonInterface {
|
|||||||
return ModuleType.from(getThing().getThingTypeUID());
|
return ModuleType.from(getThing().getThingTypeUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
default void setRefreshCapability() {
|
|
||||||
if (ModuleType.ACCOUNT.equals(getModuleType().getBridge())) {
|
|
||||||
NAThingConfiguration config = getThing().getConfiguration().as(NAThingConfiguration.class);
|
|
||||||
getCapabilities().put(new RefreshCapability(this, getScheduler(), config.refreshInterval));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default void removeRefreshCapability() {
|
|
||||||
Capability refreshCap = getCapabilities().remove(RefreshCapability.class);
|
|
||||||
if (refreshCap != null) {
|
|
||||||
refreshCap.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default void commonDispose() {
|
default void commonDispose() {
|
||||||
getCapabilities().values().forEach(Capability::dispose);
|
getCapabilities().values().forEach(Capability::dispose);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import java.util.Optional;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link CapabilityMap} is a specialized Map designed to store capabilities
|
* {@link CapabilityMap} is a specialized Map designed to store capabilities
|
||||||
@ -40,4 +41,12 @@ public class CapabilityMap extends ConcurrentHashMap<Class<?>, Capability> {
|
|||||||
T cap = (T) super.get(clazz);
|
T cap = (T) super.get(clazz);
|
||||||
return Optional.ofNullable(cap);
|
return Optional.ofNullable(cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T extends Capability> void remove(Class<?> clazz) {
|
||||||
|
@Nullable
|
||||||
|
Capability cap = super.remove(clazz);
|
||||||
|
if (cap != null) {
|
||||||
|
cap.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.netatmo.internal.handler.capability;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ParentUpdateCapability} is the class used to request data update upon initialization of a module
|
||||||
|
*
|
||||||
|
* @author Gaël L'hopital - Initial contribution
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class ParentUpdateCapability extends Capability {
|
||||||
|
private static final int DEFAULT_DELAY_S = 2;
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ParentUpdateCapability.class);
|
||||||
|
private Optional<ScheduledFuture<?>> job = Optional.empty();
|
||||||
|
|
||||||
|
public ParentUpdateCapability(CommonInterface handler) {
|
||||||
|
super(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
job = Optional.of(handler.getScheduler().schedule(() -> {
|
||||||
|
logger.debug("Requesting parents data update for Thing {}", handler.getId());
|
||||||
|
CommonInterface bridgeHandler = handler.getBridgeHandler();
|
||||||
|
if (bridgeHandler != null) {
|
||||||
|
bridgeHandler.expireData();
|
||||||
|
}
|
||||||
|
}, DEFAULT_DELAY_S, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
job.ifPresent(j -> j.cancel(true));
|
||||||
|
job = Optional.empty();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,7 +18,6 @@ import java.time.Duration;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -42,7 +41,6 @@ public class RefreshCapability extends Capability {
|
|||||||
private static final Duration OFFLINE_INTERVAL = Duration.of(15, MINUTES);
|
private static final Duration OFFLINE_INTERVAL = Duration.of(15, MINUTES);
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(RefreshCapability.class);
|
private final Logger logger = LoggerFactory.getLogger(RefreshCapability.class);
|
||||||
private final ScheduledExecutorService scheduler;
|
|
||||||
|
|
||||||
private Duration dataValidity;
|
private Duration dataValidity;
|
||||||
private Instant dataTimeStamp = Instant.now();
|
private Instant dataTimeStamp = Instant.now();
|
||||||
@ -50,10 +48,13 @@ public class RefreshCapability extends Capability {
|
|||||||
private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
|
private Optional<ScheduledFuture<?>> refreshJob = Optional.empty();
|
||||||
private boolean refreshConfigured;
|
private boolean refreshConfigured;
|
||||||
|
|
||||||
public RefreshCapability(CommonInterface handler, ScheduledExecutorService scheduler, int refreshInterval) {
|
public RefreshCapability(CommonInterface handler, int refreshInterval) {
|
||||||
super(handler);
|
super(handler);
|
||||||
this.scheduler = scheduler;
|
|
||||||
this.dataValidity = Duration.ofSeconds(Math.max(0, refreshInterval));
|
this.dataValidity = Duration.ofSeconds(Math.max(0, refreshInterval));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
this.refreshConfigured = !probing();
|
this.refreshConfigured = !probing();
|
||||||
freeJobAndReschedule(2);
|
freeJobAndReschedule(2);
|
||||||
}
|
}
|
||||||
@ -109,7 +110,7 @@ public class RefreshCapability extends Capability {
|
|||||||
refreshConfigured = true;
|
refreshConfigured = true;
|
||||||
logger.debug("Data validity period identified to be {}", dataValidity);
|
logger.debug("Data validity period identified to be {}", dataValidity);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Data validity period not yet found - data timestamp unchanged");
|
logger.debug("Data validity period not yet found, data timestamp unchanged");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataTimeStamp = tsInstant;
|
dataTimeStamp = tsInstant;
|
||||||
@ -117,8 +118,8 @@ public class RefreshCapability extends Capability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void freeJobAndReschedule(long delay) {
|
private void freeJobAndReschedule(long delay) {
|
||||||
refreshJob.ifPresent(job -> job.cancel(false));
|
refreshJob.ifPresent(job -> job.cancel(true));
|
||||||
refreshJob = Optional
|
refreshJob = Optional.ofNullable(delay == 0 ? null
|
||||||
.ofNullable(delay == 0 ? null : scheduler.schedule(() -> proceedWithUpdate(), delay, TimeUnit.SECONDS));
|
: handler.getScheduler().schedule(() -> proceedWithUpdate(), delay, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user