From ca667e39c520df7cb532ae566049a10a19c20861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20L=27hopital?= Date: Sun, 9 Apr 2023 22:21:22 +0200 Subject: [PATCH] [Netatmo] Fix duplicate id on single home (#14765) * Solve duplicate id on single home * Solving "Handler DeviceHandler of thing netatmo:welcome:compte:maison:camera tried accessing its bridge although the handler was already disposed." Signed-off-by: clinique --- .../internal/handler/CommonInterface.java | 14 ++++----- .../capability/AlarmEventCapability.java | 2 +- .../handler/capability/CameraCapability.java | 12 ++++---- .../handler/capability/HomeCapability.java | 16 ++++++++-- .../HomeSecurityThingCapability.java | 29 ++++++++++++------- .../handler/capability/PersonCapability.java | 6 ++-- .../capability/PresenceCapability.java | 2 +- 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java index 14d6823cc7a..c80eec1df16 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/CommonInterface.java @@ -121,13 +121,12 @@ public interface CommonInterface { .filter(channel -> ChannelKind.STATE.equals(channel.getKind()) && isLinked(channel.getUID())); } - default Optional getHomeHandler() { - CommonInterface bridgeHandler = getBridgeHandler(); - if (bridgeHandler != null) { - return bridgeHandler.getCapabilities().get(HomeCapability.class).isPresent() ? Optional.of(bridgeHandler) - : Optional.empty(); + default Optional recurseUpToHomeHandler(@Nullable CommonInterface handler) { + if (handler == null) { + return Optional.empty(); } - return Optional.empty(); + return handler.getCapabilities().get(HomeCapability.class).isPresent() ? Optional.of(handler) + : recurseUpToHomeHandler(handler.getBridgeHandler()); } default List getActiveChildren() { @@ -146,7 +145,8 @@ public interface CommonInterface { } default > Optional getHomeCapability(Class clazz) { - return getHomeHandler().map(handler -> handler.getCapabilities().get(clazz)).orElse(Optional.empty()); + return recurseUpToHomeHandler(this).map(handler -> handler.getCapabilities().get(clazz)) + .orElse(Optional.empty()); } default void setNewData(NAObject newData) { 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 44005b0db22..83c4a125671 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 @@ -36,7 +36,7 @@ public class AlarmEventCapability extends HomeSecurityThingCapability { @Override public List updateReadings() { - return securityCapability.map(cap -> cap.getDeviceLastEvent(handler.getId(), moduleType.apiName)) + return getSecurityCapability().map(cap -> cap.getDeviceLastEvent(handler.getId(), moduleType.apiName)) .map(event -> List.of((NAObject) event)).orElse(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 558636e49b9..fbc6418c872 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 @@ -14,7 +14,6 @@ package org.openhab.binding.netatmo.internal.handler.capability; import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*; -import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.toStringType; import java.util.ArrayList; import java.util.List; @@ -71,7 +70,7 @@ public class CameraCapability extends HomeSecurityThingCapability { String newVpnUrl = newData.getVpnUrl(); if (newVpnUrl != null && !newVpnUrl.equals(vpnUrl)) { // This will also decrease the number of requests emitted toward Netatmo API. - localUrl = newData.isLocal() ? securityCapability.map(cap -> cap.ping(newVpnUrl)).orElse(null) : null; + localUrl = newData.isLocal() ? getSecurityCapability().map(cap -> cap.ping(newVpnUrl)).orElse(null) : null; cameraHelper.setUrls(newVpnUrl, localUrl); eventHelper.setUrls(newVpnUrl, localUrl); } @@ -107,14 +106,15 @@ public class CameraCapability extends HomeSecurityThingCapability { // The channel should get triggered at last (after super and sub methods), because this allows rules to access // the new updated data from the other channels. final String eventType = event.getEventType().name(); - handler.getHomeHandler().ifPresent(homeHandler -> homeHandler.triggerChannel(CHANNEL_HOME_EVENT, eventType)); + handler.recurseUpToHomeHandler(handler) + .ifPresent(homeHandler -> homeHandler.triggerChannel(CHANNEL_HOME_EVENT, eventType)); handler.triggerChannel(CHANNEL_HOME_EVENT, eventType); } @Override public void handleCommand(String channelName, Command command) { if (command instanceof OnOffType && CHANNEL_MONITORING.equals(channelName)) { - securityCapability.ifPresent(cap -> cap.changeStatus(localUrl, OnOffType.ON.equals(command))); + getSecurityCapability().ifPresent(cap -> cap.changeStatus(localUrl, OnOffType.ON.equals(command))); } else { super.handleCommand(channelName, command); } @@ -123,7 +123,7 @@ public class CameraCapability extends HomeSecurityThingCapability { @Override protected void beforeNewData() { super.beforeNewData(); - securityCapability.ifPresent(cap -> { + getSecurityCapability().ifPresent(cap -> { NAObjectMap persons = cap.getPersons(); descriptionProvider.setStateOptions(personChannelUID, persons.values().stream() .map(p -> new StateOption(p.getId(), p.getName())).collect(Collectors.toList())); @@ -133,7 +133,7 @@ public class CameraCapability extends HomeSecurityThingCapability { @Override public List updateReadings() { List result = new ArrayList<>(); - securityCapability.ifPresent(cap -> { + getSecurityCapability().ifPresent(cap -> { HomeEvent event = cap.getDeviceLastEvent(handler.getId(), moduleType.apiName); if (event != null) { result.add(event); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java index 79891fc4356..537c1dfa6fd 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/HomeCapability.java @@ -47,7 +47,7 @@ public class HomeCapability extends RestCapability { private final Logger logger = LoggerFactory.getLogger(HomeCapability.class); private final Set featureAreas = new HashSet<>(); private final NetatmoDescriptionProvider descriptionProvider; - private Set homeIds = Set.of(); + private final Set homeIds = new HashSet<>(); public HomeCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider) { super(handler, HomeApi.class); @@ -58,7 +58,19 @@ public class HomeCapability extends RestCapability { public void initialize() { super.initialize(); HomeConfiguration config = handler.getConfiguration().as(HomeConfiguration.class); - homeIds = Set.of(config.getId(), config.energyId, config.securityId); + homeIds.add(config.getId()); + if (!config.energyId.isBlank()) { + homeIds.add(config.energyId); + } + if (!config.securityId.isBlank()) { + homeIds.add(config.securityId); + } + } + + @Override + public void dispose() { + homeIds.clear(); + super.dispose(); } @Override 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 84e5ae2c0a5..07296dcf68f 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 @@ -36,8 +36,8 @@ public class HomeSecurityThingCapability extends Capability { protected final EventChannelHelper eventHelper; private Optional webhook = Optional.empty(); - protected Optional securityCapability = Optional.empty(); - protected Optional homeCapability = Optional.empty(); + private Optional securityCapability = Optional.empty(); + private Optional homeCapability = Optional.empty(); public HomeSecurityThingCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider, List channelHelpers) { @@ -49,16 +49,23 @@ public class HomeSecurityThingCapability extends Capability { eventHelper.setModuleType(moduleType); } - @Override - public void initialize() { - super.initialize(); - securityCapability = handler.getHomeCapability(SecurityCapability.class); - homeCapability = handler.getHomeCapability(HomeCapability.class); - ApiBridgeHandler accountHandler = handler.getAccountHandler(); - if (accountHandler != null) { - webhook = accountHandler.getWebHookServlet(); - webhook.ifPresent(servlet -> servlet.registerDataListener(handler.getId(), this)); + protected Optional getSecurityCapability() { + if (securityCapability.isEmpty()) { + securityCapability = handler.getHomeCapability(SecurityCapability.class); + ApiBridgeHandler accountHandler = handler.getAccountHandler(); + if (accountHandler != null) { + webhook = accountHandler.getWebHookServlet(); + webhook.ifPresent(servlet -> servlet.registerDataListener(handler.getId(), this)); + } } + return securityCapability; + } + + protected Optional getHomeCapability() { + if (homeCapability.isEmpty()) { + homeCapability = handler.getHomeCapability(HomeCapability.class); + } + return homeCapability; } @Override 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 596fad6a565..ce73a84cafd 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 @@ -56,7 +56,7 @@ public class PersonCapability extends HomeSecurityThingCapability { @Override protected void beforeNewData() { super.beforeNewData(); - securityCapability.ifPresent(cap -> { + getSecurityCapability().ifPresent(cap -> { Stream cameras = cap.getModules().values().stream() .filter(module -> module.getType() == ModuleType.WELCOME); descriptionProvider.setStateOptions(cameraChannelUID, @@ -67,7 +67,7 @@ public class PersonCapability extends HomeSecurityThingCapability { @Override public void handleCommand(String channelName, Command command) { if ((command instanceof OnOffType) && CHANNEL_PERSON_AT_HOME.equals(channelName)) { - securityCapability.ifPresent(cap -> cap.setPersonAway(handler.getId(), OnOffType.OFF.equals(command))); + getSecurityCapability().ifPresent(cap -> cap.setPersonAway(handler.getId(), OnOffType.OFF.equals(command))); } } @@ -88,7 +88,7 @@ public class PersonCapability extends HomeSecurityThingCapability { @Override public List updateReadings() { List result = new ArrayList<>(); - securityCapability.ifPresent(cap -> { + getSecurityCapability().ifPresent(cap -> { HomeEvent event = cap.getLastPersonEvent(handler.getId()); if (event != null) { result.add(event); diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java index 05ee7e892b4..d615d7dc9f5 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/capability/PresenceCapability.java @@ -62,6 +62,6 @@ public class PresenceCapability extends CameraCapability { } private void changeFloodlightMode(FloodLightMode mode) { - securityCapability.ifPresent(cap -> cap.changeFloodlightMode(handler.getId(), mode)); + getSecurityCapability().ifPresent(cap -> cap.changeFloodlightMode(handler.getId(), mode)); } }