From 247a19d5dd2f77cb96089117fb3f0e40a0798228 Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Fri, 10 Jul 2020 19:52:00 +0200 Subject: [PATCH] [netatmo] Avoid multiple device data reading at startup Fix #5440 Signed-off-by: Laurent Garnier --- .../netatmo/internal/RefreshStrategy.java | 4 + .../handler/NetatmoDeviceHandler.java | 94 ++++++++++--------- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java index 3e540fc0d3409..89f4082da3633 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java @@ -92,4 +92,8 @@ public void expireData() { ZonedDateTime now = ZonedDateTime.now().minus(this.dataValidityPeriod, ChronoUnit.MILLIS); dataTimeStamp = now.toInstant().toEpochMilli(); } + + public boolean isSearchingRefreshInterval() { + return searchRefreshInterval && dataTimestamp0 != null; + } } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java index a4dcb8a7b5f7f..3d4c9ffcf37c9 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java @@ -55,6 +55,7 @@ public abstract class NetatmoDeviceHandler extends AbstractNetatmoThingH private static final int DEFAULT_REFRESH_INTERVAL = 300000; private final Logger logger = LoggerFactory.getLogger(NetatmoDeviceHandler.class); + private final Object updateLock = new Object(); private @Nullable ScheduledFuture refreshJob; private @Nullable RefreshStrategy refreshStrategy; private @Nullable DEVICE device; @@ -79,7 +80,7 @@ private void scheduleRefreshJob() { long delay = strategy.nextRunDelayInS(); logger.debug("Scheduling update channel thread in {} s", delay); refreshJob = scheduler.schedule(() -> { - updateChannels(); + updateChannels(false); ScheduledFuture job = refreshJob; if (job != null) { job.cancel(false); @@ -106,53 +107,62 @@ protected void updateProperties(DEVICE deviceData) { @Override protected void updateChannels() { - RefreshStrategy strategy = refreshStrategy; - if (strategy != null) { - logger.debug("Data aged of {} s", strategy.dataAge() / 1000); - if (strategy.isDataOutdated()) { - logger.debug("Trying to update channels on device {}", getId()); - childs.clear(); - - Optional newDeviceReading = Optional.empty(); - try { - newDeviceReading = updateReadings(); - } catch (RetrofitError e) { - if (logger.isDebugEnabled()) { - // we also attach the stack trace - logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e); + updateChannels(true); + } + + private void updateChannels(boolean requireDefinedRefreshInterval) { + // Avoid concurrent data readings + synchronized (updateLock) { + RefreshStrategy strategy = refreshStrategy; + if (strategy != null) { + logger.debug("Data aged of {} s", strategy.dataAge() / 1000); + boolean dataOutdated = (requireDefinedRefreshInterval && strategy.isSearchingRefreshInterval()) ? false + : strategy.isDataOutdated(); + if (dataOutdated) { + logger.debug("Trying to update channels on device {}", getId()); + childs.clear(); + + Optional newDeviceReading = Optional.empty(); + try { + newDeviceReading = updateReadings(); + } catch (RetrofitError e) { + if (logger.isDebugEnabled()) { + // we also attach the stack trace + logger.error("Unable to connect Netatmo API : {}", e.getMessage(), e); + } else { + logger.error("Unable to connect Netatmo API : {}", e.getMessage()); + } + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to connect Netatmo API : " + e.getLocalizedMessage()); + } + if (newDeviceReading.isPresent()) { + updateStatus(ThingStatus.ONLINE); + logger.debug("Successfully updated device {} readings! Now updating channels", getId()); + DEVICE theDevice = newDeviceReading.get(); + this.device = theDevice; + updateProperties(theDevice); + getDataTimestamp().ifPresent(dataTimeStamp -> { + strategy.setDataTimeStamp(dataTimeStamp, timeZoneProvider.getTimeZone()); + }); + getRadioHelper().ifPresent(helper -> helper.setModule(theDevice)); + getBridgeHandler().ifPresent(handler -> { + handler.checkForNewThings(theDevice); + }); } else { - logger.error("Unable to connect Netatmo API : {}", e.getMessage()); + logger.debug("Failed to update device {} readings! Skip updating channels", getId()); } - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Unable to connect Netatmo API : " + e.getLocalizedMessage()); - } - if (newDeviceReading.isPresent()) { - updateStatus(ThingStatus.ONLINE); - logger.debug("Successfully updated device {} readings! Now updating channels", getId()); - DEVICE theDevice = newDeviceReading.get(); - this.device = theDevice; - updateProperties(theDevice); - getDataTimestamp().ifPresent(dataTimeStamp -> { - strategy.setDataTimeStamp(dataTimeStamp, timeZoneProvider.getTimeZone()); - }); - getRadioHelper().ifPresent(helper -> helper.setModule(theDevice)); - getBridgeHandler().ifPresent(handler -> { - handler.checkForNewThings(theDevice); + // Be sure that all channels for the modules will be updated with refreshed data + childs.forEach((childId, moduleData) -> { + findNAThing(childId).map(NetatmoModuleHandler.class::cast).ifPresent(naChildModule -> { + naChildModule.setRefreshRequired(true); + }); }); } else { - logger.debug("Failed to update device {} readings! Skip updating channels", getId()); + logger.debug("Data still valid for device {}", getId()); } - // Be sure that all channels for the modules will be updated with refreshed data - childs.forEach((childId, moduleData) -> { - findNAThing(childId).map(NetatmoModuleHandler.class::cast).ifPresent(naChildModule -> { - naChildModule.setRefreshRequired(true); - }); - }); - } else { - logger.debug("Data still valid for device {}", getId()); + super.updateChannels(); + updateChildModules(); } - super.updateChannels(); - updateChildModules(); } }