/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.config.discovery.internal; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.config.discovery.UpnpDiscoveryParticipant; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.jupnp.UpnpService; import org.jupnp.model.meta.LocalDevice; import org.jupnp.model.meta.RemoteDevice; import org.jupnp.registry.Registry; import org.jupnp.registry.RegistryListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is a {@link DiscoveryService} implementation, which can find UPnP devices in the network. * Support for further devices can be added by implementing and registering a {@link UpnpDiscoveryParticipant}. * * @author Kai Kreuzer - Initial contribution * @author Andre Fuechsel - Added call of removeOlderResults * */ public class UpnpDiscoveryService extends AbstractDiscoveryService implements RegistryListener { private final Logger logger = LoggerFactory.getLogger(UpnpDiscoveryService.class); private Set<UpnpDiscoveryParticipant> participants = new CopyOnWriteArraySet<>(); public UpnpDiscoveryService() { super(5); } private UpnpService upnpService; @Override protected void activate(Map<String, Object> configProperties) { super.activate(configProperties); startScan(); } protected void setUpnpService(UpnpService upnpService) { this.upnpService = upnpService; } protected void unsetUpnpService(UpnpService upnpService) { this.upnpService = null; } protected void addUpnpDiscoveryParticipant(UpnpDiscoveryParticipant participant) { this.participants.add(participant); if (upnpService != null) { Collection<RemoteDevice> devices = upnpService.getRegistry().getRemoteDevices(); for (RemoteDevice device : devices) { DiscoveryResult result = participant.createResult(device); if (result != null) { thingDiscovered(result); } } } } protected void removeUpnpDiscoveryParticipant(UpnpDiscoveryParticipant participant) { this.participants.remove(participant); } @Override public Set<ThingTypeUID> getSupportedThingTypes() { Set<ThingTypeUID> supportedThingTypes = new HashSet<>(); for (UpnpDiscoveryParticipant participant : participants) { supportedThingTypes.addAll(participant.getSupportedThingTypeUIDs()); } return supportedThingTypes; } @Override protected void startBackgroundDiscovery() { upnpService.getRegistry().addListener(this); } @Override protected void stopBackgroundDiscovery() { upnpService.getRegistry().removeListener(this); } @Override protected void startScan() { for (RemoteDevice device : upnpService.getRegistry().getRemoteDevices()) { remoteDeviceAdded(upnpService.getRegistry(), device); } upnpService.getRegistry().addListener(this); upnpService.getControlPoint().search(); } @Override protected synchronized void stopScan() { removeOlderResults(getTimestampOfLastScan()); super.stopScan(); if (!isBackgroundDiscoveryEnabled()) { upnpService.getRegistry().removeListener(this); } } @Override public void remoteDeviceAdded(Registry registry, RemoteDevice device) { for (UpnpDiscoveryParticipant participant : participants) { try { DiscoveryResult result = participant.createResult(device); if (result != null) { thingDiscovered(result); } } catch (Exception e) { logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e); } } } @Override public void remoteDeviceRemoved(Registry registry, RemoteDevice device) { for (UpnpDiscoveryParticipant participant : participants) { try { ThingUID thingUID = participant.getThingUID(device); if (thingUID != null) { thingRemoved(thingUID); } } catch (Exception e) { logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e); } } } @Override public void remoteDeviceUpdated(Registry registry, RemoteDevice device) { } @Override public void localDeviceAdded(Registry registry, LocalDevice device) { } @Override public void localDeviceRemoved(Registry registry, LocalDevice device) { } @Override public void beforeShutdown(Registry registry) { } @Override public void afterShutdown() { } @Override public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) { } @Override public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device, Exception ex) { } }