]> git.basschouten.com Git - openhab-addons.git/commitdiff
[wemo] Fix UPnP resubscription after lost network connection (#12648)
authorJacob Laursen <jacob-github@vindvejr.dk>
Mon, 25 Apr 2022 09:16:47 +0000 (11:16 +0200)
committerGitHub <noreply@github.com>
Mon, 25 Apr 2022 09:16:47 +0000 (11:16 +0200)
Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
17 files changed:
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoUtil.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBaseThingHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoInsightHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMotionHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoSwitchHandler.java
bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/http/WemoHttpCall.java
itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/handler/test/WemoInsightHandlerTest.java
itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/test/GenericWemoOSGiTest.java

index 64706014cde425b8166edbbd1e2acda2e22b3121..3c674af2cbc303b9799e0ebdce21304ff878ee6d 100644 (file)
  */
 package org.openhab.binding.wemo.internal;
 
-import java.util.Collections;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.core.thing.ThingTypeUID;
@@ -126,14 +123,12 @@ public class WemoBindingConstants {
     public static final String INSIGHTACTION = "insight";
     public static final String INSIGHTEVENT = "insight1";
 
-    public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
+    public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES = Set.of(THING_TYPE_BRIDGE);
 
-    public static final Set<ThingTypeUID> SUPPORTED_LIGHT_THING_TYPES = Collections.singleton(THING_TYPE_MZ100);
+    public static final Set<ThingTypeUID> SUPPORTED_LIGHT_THING_TYPES = Set.of(THING_TYPE_MZ100);
 
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections
-            .unmodifiableSet(Stream
-                    .of(THING_TYPE_SOCKET, THING_TYPE_INSIGHT, THING_TYPE_LIGHTSWITCH, THING_TYPE_MOTION,
-                            THING_TYPE_BRIDGE, THING_TYPE_MZ100, THING_TYPE_MAKER, THING_TYPE_COFFEE, THING_TYPE_DIMMER,
-                            THING_TYPE_CROCKPOT, THING_TYPE_PURIFIER, THING_TYPE_HUMIDIFIER, THING_TYPE_HEATER)
-                    .collect(Collectors.toSet()));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_SOCKET, THING_TYPE_INSIGHT,
+            THING_TYPE_LIGHTSWITCH, THING_TYPE_MOTION, THING_TYPE_BRIDGE, THING_TYPE_MZ100, THING_TYPE_MAKER,
+            THING_TYPE_COFFEE, THING_TYPE_DIMMER, THING_TYPE_CROCKPOT, THING_TYPE_PURIFIER, THING_TYPE_HUMIDIFIER,
+            THING_TYPE_HEATER);
 }
index 75e5dd7f40e59de664f9d70c1041f04f042db500..8a22a09b60e3e3b7e7e940d00b81357ac828f2d4 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Set;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.discovery.WemoLinkDiscoveryService;
 import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
 import org.openhab.binding.wemo.internal.handler.WemoCoffeeHandler;
@@ -67,6 +68,7 @@ public class WemoHandlerFactory extends BaseThingHandlerFactory {
     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = WemoBindingConstants.SUPPORTED_THING_TYPES;
 
     private final UpnpIOService upnpIOService;
+    private final UpnpService upnpService;
     private @Nullable WemoHttpCallFactory wemoHttpCallFactory;
 
     @Override
@@ -77,8 +79,9 @@ public class WemoHandlerFactory extends BaseThingHandlerFactory {
     private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
 
     @Activate
-    public WemoHandlerFactory(final @Reference UpnpIOService upnpIOService) {
+    public WemoHandlerFactory(final @Reference UpnpIOService upnpIOService, @Reference UpnpService upnpService) {
         this.upnpIOService = upnpIOService;
+        this.upnpService = upnpService;
     }
 
     @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
@@ -108,46 +111,46 @@ public class WemoHandlerFactory extends BaseThingHandlerFactory {
         } else if (WemoBindingConstants.THING_TYPE_INSIGHT.equals(thing.getThingTypeUID())) {
             logger.debug("Creating a WemoInsightHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get(UDN));
-            return new WemoInsightHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoInsightHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (WemoBindingConstants.THING_TYPE_SOCKET.equals(thing.getThingTypeUID())
                 || WemoBindingConstants.THING_TYPE_LIGHTSWITCH.equals(thing.getThingTypeUID())) {
             logger.debug("Creating a WemoSwitchHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get(UDN));
-            return new WemoSwitchHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoSwitchHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (WemoBindingConstants.THING_TYPE_MOTION.equals(thing.getThingTypeUID())) {
             logger.debug("Creating a WemoMotionHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get(UDN));
-            return new WemoMotionHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoMotionHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_MAKER)) {
             logger.debug("Creating a WemoMakerHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get(UDN));
-            return new WemoMakerHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoMakerHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_COFFEE)) {
             logger.debug("Creating a WemoCoffeeHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get(UDN));
-            return new WemoCoffeeHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoCoffeeHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_DIMMER)) {
             logger.debug("Creating a WemoDimmerHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get("udn"));
-            return new WemoDimmerHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoDimmerHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_CROCKPOT)) {
             logger.debug("Creating a WemoCockpotHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get("udn"));
-            return new WemoCrockpotHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoCrockpotHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_PURIFIER)) {
             logger.debug("Creating a WemoHolmesHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get("udn"));
-            return new WemoHolmesHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoHolmesHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_HUMIDIFIER)) {
             logger.debug("Creating a WemoHolmesHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get("udn"));
-            return new WemoHolmesHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoHolmesHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_HEATER)) {
             logger.debug("Creating a WemoHolmesHandler for thing '{}' with UDN '{}'", thing.getUID(),
                     thing.getConfiguration().get("udn"));
-            return new WemoHolmesHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoHolmesHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_MZ100)) {
-            return new WemoLightHandler(thing, upnpIOService, wemoHttpcaller);
+            return new WemoLightHandler(thing, upnpIOService, upnpService, wemoHttpcaller);
         } else {
             logger.warn("ThingHandler not found for {}", thingTypeUID);
             return null;
index 22046a040a3f90737605d2c6dbd70467a884dd88..fa5bd4e344f231367a1f77ad3259473bd946a6a1 100644 (file)
  */
 package org.openhab.binding.wemo.internal;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.function.BiFunction;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.io.net.http.HttpUtil;
 import org.w3c.dom.CharacterData;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -34,8 +31,6 @@ import org.w3c.dom.Node;
 @NonNullByDefault
 public class WemoUtil {
 
-    public static BiFunction<String, Integer, Boolean> serviceAvailableFunction = WemoUtil::servicePing;
-
     public static String substringBefore(@Nullable String string, String pattern) {
         if (string != null) {
             int pos = string.indexOf(pattern);
@@ -125,15 +120,6 @@ public class WemoUtil {
         return unescapedOutput.toString();
     }
 
-    private static boolean servicePing(String host, int port) {
-        try {
-            HttpUtil.executeUrl("GET", "http://" + host + ":" + port, 250);
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
     private static Map<String, String> buildBuiltinXMLEntityMap() {
         Map<String, String> entities = new HashMap<String, String>(10);
         entities.put("lt", "<");
index ec11ee57b286348e5299c71acb9692ca1fa936d0..1ce737d04996190dc703bb057cebd3cfed5780be 100644 (file)
@@ -15,14 +15,16 @@ package org.openhab.binding.wemo.internal.handler;
 import java.net.URL;
 import java.time.Instant;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
+import org.jupnp.model.message.header.RootDeviceHeader;
 import org.openhab.binding.wemo.internal.WemoBindingConstants;
-import org.openhab.binding.wemo.internal.WemoUtil;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -48,39 +50,36 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
     private static final int SUBSCRIPTION_RENEWAL_INTERVAL_SECONDS = 60;
 
     private final Logger logger = LoggerFactory.getLogger(WemoBaseThingHandler.class);
+    private final UpnpIOService service;
+    private final UpnpService upnpService;
 
-    protected @Nullable UpnpIOService service;
     protected WemoHttpCall wemoHttpCaller;
 
     private @Nullable String host;
     private Map<String, Instant> subscriptions = new ConcurrentHashMap<String, Instant>();
     private @Nullable ScheduledFuture<?> subscriptionRenewalJob;
 
-    public WemoBaseThingHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+    public WemoBaseThingHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
         super(thing);
         this.service = upnpIOService;
+        this.upnpService = upnpService;
         this.wemoHttpCaller = wemoHttpCaller;
     }
 
     @Override
     public void initialize() {
-        UpnpIOService service = this.service;
-        if (service != null) {
-            logger.debug("Registering UPnP participant for {}", getThing().getUID());
-            service.registerParticipant(this);
-            initializeHost();
-        }
+        logger.debug("Registering UPnP participant for {}", getThing().getUID());
+        service.registerParticipant(this);
+        initializeHost();
     }
 
     @Override
     public void dispose() {
         removeSubscriptions();
-        UpnpIOService service = this.service;
-        if (service != null) {
-            logger.debug("Unregistering UPnP participant for {}", getThing().getUID());
-            service.unregisterParticipant(this);
-        }
+        logger.debug("Unregistering UPnP participant for {}", getThing().getUID());
         cancelSubscriptionRenewalJob();
+        service.unregisterParticipant(this);
     }
 
     @Override
@@ -90,7 +89,20 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
 
     @Override
     public void onStatusChanged(boolean status) {
-        // can be overridden by subclasses
+        if (status) {
+            logger.debug("UPnP device {} for {} is present", getUDN(), getThing().getUID());
+            if (service.isRegistered(this)) {
+                // After successful discovery, try to subscribe again.
+                renewSubscriptions();
+            }
+        } else {
+            logger.info("UPnP device {} for {} is absent", getUDN(), getThing().getUID());
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR);
+            // Expire subscriptions.
+            for (Entry<String, Instant> subscription : subscriptions.entrySet()) {
+                subscription.setValue(Instant.MIN);
+            }
+        }
     }
 
     @Override
@@ -111,12 +123,11 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
 
     @Override
     public @Nullable String getUDN() {
-        return (String) this.getThing().getConfiguration().get(WemoBindingConstants.UDN);
+        return (String) this.getConfig().get(WemoBindingConstants.UDN);
     }
 
     protected boolean isUpnpDeviceRegistered() {
-        UpnpIOService service = this.service;
-        return service != null && service.isRegistered(this);
+        return service.isRegistered(this);
     }
 
     protected void addSubscription(String serviceId) {
@@ -128,43 +139,12 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
             logger.debug("Adding first GENA subscription for {}, scheduling renewal job", getUDN());
             scheduleSubscriptionRenewalJob();
         }
-        subscriptions.put(serviceId, Instant.ofEpochSecond(0));
-        UpnpIOService service = this.service;
-        if (service == null) {
-            return;
-        }
-        if (!service.isRegistered(this)) {
-            logger.debug("Registering UPnP participant for {}", getUDN());
-            service.registerParticipant(this);
-        }
-        if (!service.isRegistered(this)) {
-            logger.debug("Trying to add GENA subscription {} for {}, but service is not registered", serviceId,
-                    getUDN());
-            return;
-        }
-        logger.debug("Adding GENA subscription {} for {}", serviceId, getUDN());
+        subscriptions.put(serviceId, Instant.MIN);
+        logger.debug("Adding GENA subscription {} for {}, participant is {}", serviceId, getUDN(),
+                service.isRegistered(this) ? "registered" : "not registered");
         service.addSubscription(this, serviceId, WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS);
     }
 
-    protected void removeSubscription(String serviceId) {
-        UpnpIOService service = this.service;
-        if (service == null) {
-            return;
-        }
-        subscriptions.remove(serviceId);
-        if (subscriptions.isEmpty()) {
-            logger.debug("Removing last GENA subscription for {}, cancelling renewal job", getUDN());
-            cancelSubscriptionRenewalJob();
-        }
-        if (!service.isRegistered(this)) {
-            logger.debug("Trying to remove GENA subscription {} for {}, but service is not registered", serviceId,
-                    getUDN());
-            return;
-        }
-        logger.debug("Unsubscribing {} from service {}", getUDN(), serviceId);
-        service.removeSubscription(this, serviceId);
-    }
-
     private void scheduleSubscriptionRenewalJob() {
         cancelSubscriptionRenewalJob();
         this.subscriptionRenewalJob = scheduler.scheduleWithFixedDelay(this::renewSubscriptions,
@@ -179,19 +159,14 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
         this.subscriptionRenewalJob = null;
     }
 
-    private void renewSubscriptions() {
+    private synchronized void renewSubscriptions() {
         if (subscriptions.isEmpty()) {
             return;
         }
-        UpnpIOService service = this.service;
-        if (service == null) {
-            return;
-        }
-        if (!service.isRegistered(this)) {
-            service.registerParticipant(this);
-        }
         if (!service.isRegistered(this)) {
-            logger.debug("Trying to renew GENA subscriptions for {}, but service is not registered", getUDN());
+            logger.debug("Participant not registered when renewing GENA subscriptions for {}, starting UPnP discovery",
+                    getUDN());
+            upnpService.getControlPoint().search(new RootDeviceHeader());
             return;
         }
         logger.debug("Renewing GENA subscriptions for {}", getUDN());
@@ -210,16 +185,8 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
         if (subscriptions.isEmpty()) {
             return;
         }
-        UpnpIOService service = this.service;
-        if (service == null) {
-            return;
-        }
-        if (!service.isRegistered(this)) {
-            logger.debug("Trying to remove GENA subscriptions for {}, but service is not registered",
-                    getThing().getUID());
-            return;
-        }
-        logger.debug("Removing GENA subscriptions for {}", getUDN());
+        logger.debug("Removing GENA subscriptions for {}, participant is {}", getUDN(),
+                service.isRegistered(this) ? "registered" : "not registered");
         subscriptions.forEach((serviceId, lastRenewed) -> {
             logger.debug("Removing subscription for service {}", serviceId);
             service.removeSubscription(this, serviceId);
@@ -234,16 +201,8 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
                     "@text/config-status.error.missing-ip");
             return null;
         }
-        int portCheckStart = 49151;
-        int portCheckStop = 49157;
-        String port = null;
-        for (int i = portCheckStart; i < portCheckStop; i++) {
-            if (WemoUtil.serviceAvailableFunction.apply(host, i)) {
-                port = String.valueOf(i);
-                break;
-            }
-        }
-        if (port == null) {
+        int port = scanForPort(host);
+        if (port == 0) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                     "@text/config-status.error.missing-url");
             return null;
@@ -263,13 +222,27 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
         host = getHostFromService();
     }
 
-    private @Nullable String getHostFromService() {
-        UpnpIOService service = this.service;
-        if (service != null) {
-            URL descriptorURL = service.getDescriptorURL(this);
-            if (descriptorURL != null) {
-                return descriptorURL.getHost();
+    private int scanForPort(String host) {
+        int portCheckStart = 49151;
+        int portCheckStop = 49157;
+        int port = 0;
+        for (int portCheck = portCheckStart; portCheck < portCheckStop; portCheck++) {
+            String urlProbe = "http://" + host + ":" + portCheck;
+            logger.trace("Probing {} to find port", urlProbe);
+            if (!wemoHttpCaller.probeURL(urlProbe)) {
+                continue;
             }
+            port = portCheck;
+            logger.trace("Successfully detected port {}", port);
+            break;
+        }
+        return port;
+    }
+
+    private @Nullable String getHostFromService() {
+        URL descriptorURL = service.getDescriptorURL(this);
+        if (descriptorURL != null) {
+            return descriptorURL.getHost();
         }
         return null;
     }
index bd16e5bf4e1f132c401c98411f70fbf8441acd92..3912223ccfde89126bb000a8ab65ced13d7f326a 100644 (file)
@@ -29,6 +29,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -69,8 +70,9 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
 
         logger.debug("Creating a WemoCoffeeHandler for thing '{}'", getThing().getUID());
     }
index a2e76beea1882fbe01b3da9ce623e0a166a19b7a..efec9447b2ad847afe9c1e0ebdf89ab417bc2c5e 100644 (file)
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -60,8 +61,9 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
 
         logger.debug("Creating a WemoCrockpotHandler for thing '{}'", getThing().getUID());
     }
index 846fecb9f7bbc4c68d6aa9dc5e22438971f5bf0a..1eb0b75a037716b99cdcd58ab302ffbbbcc9fa5f 100644 (file)
@@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -73,8 +74,9 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
      */
     private static final int DIM_STEPSIZE = 5;
 
-    public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
 
         logger.debug("Creating a WemoDimmerHandler for thing '{}'", getThing().getUID());
     }
index ae84e0806e79539740474999a4eca0ea46967ad8..40b74df37e54463390b875a56f2b9ec4a965663d 100644 (file)
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
 import org.openhab.core.library.types.OnOffType;
@@ -52,8 +53,8 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService, WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
 
         logger.debug("Creating a WemoHandler for thing '{}'", getThing().getUID());
     }
index 5802c6c55eea0a94cb12ee138448a2ec7cff2a13..828069edab8d9e43d07e4415623975b6848ce813 100644 (file)
@@ -30,6 +30,7 @@ import javax.xml.parsers.ParserConfigurationException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -74,8 +75,9 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
 
         logger.debug("Creating a WemoHolmesHandler for thing '{}'", getThing().getUID());
     }
index 19ad6e2538bef57921e3fd274720536e9f44e6e1..501966b123b4458dd2d7e9ca14d0e43417eee944 100644 (file)
@@ -20,6 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.InsightParser;
 import org.openhab.binding.wemo.internal.WemoBindingConstants;
 import org.openhab.binding.wemo.internal.WemoPowerBank;
@@ -51,8 +52,9 @@ public class WemoInsightHandler extends WemoHandler {
     private int currentPowerSlidingSeconds;
     private int currentPowerDeltaTrigger;
 
-    public WemoInsightHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoInsightHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
     }
 
     @Override
index 2956ea3c9316d7f751910cdc4f484eb7a6ce6103..668280a53062bd37166a48663ae33e06c370e5af 100644 (file)
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -70,8 +71,9 @@ public class WemoLightHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoLightHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
-        super(thing, upnpIOService, wemoHttpcaller);
+    public WemoLightHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpcaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpcaller);
 
         logger.debug("Creating a WemoLightHandler for thing '{}'", getThing().getUID());
     }
index a94d378a4c50e75e661437cca4008c0bbe94d06e..1f29f9d9d34b9488b410befac73ad89ac77b9f1f 100644 (file)
@@ -26,6 +26,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -62,8 +63,9 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
 
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    public WemoMakerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
-        super(thing, upnpIOService, wemoHttpcaller);
+    public WemoMakerHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpcaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpcaller);
 
         logger.debug("Creating a WemoMakerHandler for thing '{}'", getThing().getUID());
     }
index f51bd09af5dc76ed2f1d5876c6792433e6758bfc..b591fd3705f8f6ddc09ec3ac2f6e22fa09ec76e4 100644 (file)
@@ -17,6 +17,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.WemoBindingConstants;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -40,8 +41,9 @@ public class WemoMotionHandler extends WemoHandler {
     private final Logger logger = LoggerFactory.getLogger(WemoMotionHandler.class);
     private final Map<String, String> stateMap = new ConcurrentHashMap<String, String>();
 
-    public WemoMotionHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoMotionHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
     }
 
     @Override
index 99c6668efbe68af87a177b7b77b19509bbae3244..cd54b98236a09c00b23c2571c682dff96fce1641 100644 (file)
@@ -17,6 +17,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.jupnp.UpnpService;
 import org.openhab.binding.wemo.internal.WemoBindingConstants;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -39,8 +40,9 @@ public class WemoSwitchHandler extends WemoHandler {
     private final Logger logger = LoggerFactory.getLogger(WemoSwitchHandler.class);
     private final Map<String, String> stateMap = new ConcurrentHashMap<String, String>();
 
-    public WemoSwitchHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
-        super(thing, upnpIOService, wemoHttpCaller);
+    public WemoSwitchHandler(Thing thing, UpnpIOService upnpIOService, UpnpService upnpService,
+            WemoHttpCall wemoHttpCaller) {
+        super(thing, upnpIOService, upnpService, wemoHttpCaller);
     }
 
     @Override
index 30314d7cff014a4429ebf2a909d216d0eb6534ea..48524e9546270bc5bda3a0ce88de2630c5da312a 100644 (file)
@@ -48,4 +48,13 @@ public class WemoHttpCall {
 
         return responseBody;
     }
+
+    public boolean probeURL(String url) {
+        try {
+            HttpUtil.executeUrl("GET", url, 250);
+            return true;
+        } catch (IOException e) {
+            return false;
+        }
+    }
 }
index a54265398fa2a70f3acc790a3f1b515945438f0f..1a2a86124fd5a700e16638715e733ab1d87b551f 100644 (file)
@@ -143,7 +143,7 @@ public class WemoInsightHandlerTest {
         String channelToWatch;
 
         public MockWemoInsightHandler(Thing thing, String channelToWatch) {
-            super(thing, null, new WemoHttpCall());
+            super(thing, null, null, new WemoHttpCall());
             this.channelToWatch = channelToWatch;
         }
 
index 98ffd9fdbc2c685accf4aeace3ef948a12063211..ad8e44052425b8e7dbe67e950a13be103860b84e 100644 (file)
@@ -40,7 +40,6 @@ import org.jupnp.model.types.UDN;
 import org.mockito.Mockito;
 import org.openhab.binding.wemo.internal.WemoBindingConstants;
 import org.openhab.binding.wemo.internal.WemoHttpCallFactory;
-import org.openhab.binding.wemo.internal.WemoUtil;
 import org.openhab.binding.wemo.internal.http.WemoHttpCall;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.io.transport.upnp.UpnpIOService;
@@ -101,8 +100,6 @@ public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
     protected Thing thing;
 
     protected void setUpServices() throws IOException {
-        WemoUtil.serviceAvailableFunction = (host, port) -> true;
-
         // StorageService is required from the ManagedThingProvider
         VolatileStorageService volatileStorageService = new VolatileStorageService();
         registerService(volatileStorageService);
@@ -123,6 +120,7 @@ public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
         assertThat(upnpIOService, is(notNullValue()));
 
         mockCaller = Mockito.spy(new WemoHttpCall());
+        doReturn(true).when(mockCaller).probeURL(any());
         WemoHttpCallFactory wemoHttpCallFactory = () -> mockCaller;
         registerService(wemoHttpCallFactory, WemoHttpCallFactory.class.getName());