[mdns] Cancel removal task on manual scan (#2647)

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2021-12-30 10:18:13 +01:00 committed by GitHub
parent 646640094a
commit 33f6651972
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 34 deletions

View File

@ -160,13 +160,8 @@ public class MDNSDiscoveryService extends AbstractDiscoveryService implements Se
}
logger.debug("{} services found for {}; duration: {}ms", services.length, participant.getServiceType(),
System.currentTimeMillis() - start);
for (ServiceInfo service : services) {
DiscoveryResult result = participant.createResult(service);
if (result != null) {
final DiscoveryResult resultNew = getLocalizedDiscoveryResult(result,
FrameworkUtil.getBundle(participant.getClass()));
thingDiscovered(resultNew);
}
for (ServiceInfo serviceInfo : services) {
createDiscoveryResult(participant, serviceInfo);
}
}
}
@ -202,21 +197,7 @@ public class MDNSDiscoveryService extends AbstractDiscoveryService implements Se
public void serviceRemoved(@NonNullByDefault({}) ServiceEvent serviceEvent) {
for (MDNSDiscoveryParticipant participant : participants) {
if (participant.getServiceType().equals(serviceEvent.getType())) {
try {
ThingUID thingUID = participant.getThingUID(serviceEvent.getInfo());
if (thingUID != null) {
ServiceInfo serviceInfo = serviceEvent.getInfo();
long gracePeriod = participant.getRemovalGracePeriodSeconds(serviceInfo);
if (gracePeriod <= 0) {
thingRemoved(thingUID);
} else {
cancelRemovalTask(serviceInfo);
scheduleRemovalTask(thingUID, serviceInfo, gracePeriod);
}
}
} catch (Exception e) {
logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e);
}
removeDiscoveryResult(participant, serviceEvent.getInfo());
}
}
}
@ -230,22 +211,43 @@ public class MDNSDiscoveryService extends AbstractDiscoveryService implements Se
if (isBackgroundDiscoveryEnabled()) {
for (MDNSDiscoveryParticipant participant : participants) {
if (participant.getServiceType().equals(serviceEvent.getType())) {
try {
DiscoveryResult result = participant.createResult(serviceEvent.getInfo());
if (result != null) {
cancelRemovalTask(serviceEvent.getInfo());
final DiscoveryResult resultNew = getLocalizedDiscoveryResult(result,
FrameworkUtil.getBundle(participant.getClass()));
thingDiscovered(resultNew);
}
} catch (Exception e) {
logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e);
}
createDiscoveryResult(participant, serviceEvent.getInfo());
}
}
}
}
private void createDiscoveryResult(MDNSDiscoveryParticipant participant, ServiceInfo serviceInfo) {
try {
DiscoveryResult result = participant.createResult(serviceInfo);
if (result != null) {
cancelRemovalTask(serviceInfo);
final DiscoveryResult resultNew = getLocalizedDiscoveryResult(result,
FrameworkUtil.getBundle(participant.getClass()));
thingDiscovered(resultNew);
}
} catch (Exception e) {
logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e);
}
}
private void removeDiscoveryResult(MDNSDiscoveryParticipant participant, ServiceInfo serviceInfo) {
try {
ThingUID thingUID = participant.getThingUID(serviceInfo);
if (thingUID != null) {
long gracePeriod = participant.getRemovalGracePeriodSeconds(serviceInfo);
if (gracePeriod <= 0) {
thingRemoved(thingUID);
} else {
cancelRemovalTask(serviceInfo);
scheduleRemovalTask(thingUID, serviceInfo, gracePeriod);
}
}
} catch (Exception e) {
logger.error("Participant '{}' threw an exception", participant.getClass().getName(), e);
}
}
/**
* If the device has been scheduled to be removed, cancel its respective removal task.
*

View File

@ -56,4 +56,8 @@ Fragment-Host: org.openhab.core.config.discovery.mdns
org.openhab.core.io.console;version='[3.3.0,3.3.1)',\
org.openhab.core.io.transport.mdns;version='[3.3.0,3.3.1)',\
org.openhab.core.test;version='[3.3.0,3.3.1)',\
org.openhab.core.thing;version='[3.3.0,3.3.1)'
org.openhab.core.thing;version='[3.3.0,3.3.1)',\
net.bytebuddy.byte-buddy;version='[1.12.1,1.12.2)',\
net.bytebuddy.byte-buddy-agent;version='[1.12.1,1.12.2)',\
org.mockito.mockito-core;version='[4.1.0,4.1.1)',\
org.objenesis;version='[3.2.0,3.2.1)'

View File

@ -14,15 +14,28 @@ package org.openhab.core.config.discovery.mdns.internal;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Random;
import java.util.Set;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.core.config.discovery.DiscoveryListener;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
import org.openhab.core.test.java.JavaOSGiTest;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
@ -42,6 +55,44 @@ public class MDNSDiscoveryServiceOSGiTest extends JavaOSGiTest {
assertThat(mdnsDiscoveryService, is(notNullValue()));
}
@Test
public void testThingDiscoveredAndRemoved() {
String serviceType = "_http._tcp.local.";
ThingTypeUID thingTypeUID = new ThingTypeUID("myBinding", "myThingType");
ThingUID thingUID = new ThingUID(thingTypeUID, "test" + new Random().nextInt(999999999));
Set<ThingTypeUID> thingTypeUIDs = Set.of(thingTypeUID);
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).build();
MDNSDiscoveryParticipant mockMDNSDiscoveryParticipant = mock(MDNSDiscoveryParticipant.class);
when(mockMDNSDiscoveryParticipant.getSupportedThingTypeUIDs()).thenReturn(thingTypeUIDs);
when(mockMDNSDiscoveryParticipant.getServiceType()).thenReturn(serviceType);
when(mockMDNSDiscoveryParticipant.createResult(any())).thenReturn(discoveryResult);
when(mockMDNSDiscoveryParticipant.getThingUID(any())).thenReturn(thingUID);
mdnsDiscoveryService.addMDNSDiscoveryParticipant(mockMDNSDiscoveryParticipant);
assertThat(mdnsDiscoveryService.getSupportedThingTypes(), is(thingTypeUIDs));
ServiceEvent mockServiceEvent = mock(ServiceEvent.class);
when(mockServiceEvent.getType()).thenReturn(serviceType);
when(mockServiceEvent.getInfo()).thenReturn(ServiceInfo.create(serviceType, "name", 80, "text"));
DiscoveryListener mockDiscoveryListener = mock(DiscoveryListener.class);
mdnsDiscoveryService.addDiscoveryListener(mockDiscoveryListener);
mdnsDiscoveryService.serviceAdded(mockServiceEvent);
verify(mockDiscoveryListener, times(1)).thingDiscovered(mdnsDiscoveryService, discoveryResult);
verifyNoMoreInteractions(mockDiscoveryListener);
mdnsDiscoveryService.serviceResolved(mockServiceEvent);
verify(mockDiscoveryListener, times(2)).thingDiscovered(mdnsDiscoveryService, discoveryResult);
verifyNoMoreInteractions(mockDiscoveryListener);
mdnsDiscoveryService.serviceRemoved(mockServiceEvent);
verify(mockDiscoveryListener, times(1)).thingRemoved(mdnsDiscoveryService, thingUID);
verifyNoMoreInteractions(mockDiscoveryListener);
}
/**
* Test that configuring the background discovery dynamically via config admin is effective.
*/