diff --git a/bundles/org.openhab.core.config.discovery.addon.ip/src/main/java/org/openhab/core/config/discovery/addon/ip/IpAddonFinder.java b/bundles/org.openhab.core.config.discovery.addon.ip/src/main/java/org/openhab/core/config/discovery/addon/ip/IpAddonFinder.java index 5ecaace6278..0719158f127 100644 --- a/bundles/org.openhab.core.config.discovery.addon.ip/src/main/java/org/openhab/core/config/discovery/addon/ip/IpAddonFinder.java +++ b/bundles/org.openhab.core.config.discovery.addon.ip/src/main/java/org/openhab/core/config/discovery/addon/ip/IpAddonFinder.java @@ -36,6 +36,7 @@ import java.util.Objects; import java.util.Set; import java.util.StringTokenizer; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -43,16 +44,21 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.addon.Addon; import org.openhab.core.addon.AddonDiscoveryMethod; import org.openhab.core.addon.AddonInfo; import org.openhab.core.addon.AddonMatchProperty; import org.openhab.core.addon.AddonParameter; +import org.openhab.core.addon.AddonService; import org.openhab.core.common.ThreadPoolManager; import org.openhab.core.config.discovery.addon.AddonFinder; import org.openhab.core.config.discovery.addon.BaseAddonFinder; import org.openhab.core.net.NetUtil; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,6 +154,7 @@ public class IpAddonFinder extends BaseAddonFinder { private final Logger logger = LoggerFactory.getLogger(IpAddonFinder.class); private final ScheduledExecutorService scheduler = ThreadPoolManager .getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON); + private final Set addonServices = new CopyOnWriteArraySet<>(); private @Nullable Future scanJob = null; Set suggestions = new HashSet<>(); @@ -169,6 +176,15 @@ public void setAddonCandidates(List candidates) { startScan(); } + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) + protected void addAddonService(AddonService featureService) { + this.addonServices.add(featureService); + } + + protected void removeAddonService(AddonService featureService) { + this.addonServices.remove(featureService); + } + private void startScan() { // The setAddonCandidates() method is called for each info provider. // In order to do the scan only once, but on the full set of candidates, we have to delay the execution. @@ -197,6 +213,12 @@ private void scan() { logger.trace("Checking candidate: {}", candidate.getUID()); + // skip scanning if already installed + if (isAddonInstalled(candidate.getUID())) { + logger.trace("Skipping {}, already installed", candidate.getUID()); + continue; + } + Map parameters = method.getParameters().stream() .collect(Collectors.toMap(AddonParameter::getName, AddonParameter::getValue)); Map matchProperties = method.getMatchProperties().stream() @@ -342,4 +364,14 @@ public Set getSuggestedAddons() { public String getServiceName() { return SERVICE_NAME; } + + private boolean isAddonInstalled(String addonId) { + for (AddonService addonService : addonServices) { + Addon addon = addonService.getAddon(addonId, null); + if (addon != null && addon.isInstalled()) { + return true; + } + } + return false; + } }