diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java index 64706014c..3c674af2c 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java @@ -12,10 +12,7 @@ */ 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 SUPPORTED_BRIDGE_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE); + public static final Set SUPPORTED_BRIDGE_THING_TYPES = Set.of(THING_TYPE_BRIDGE); - public static final Set SUPPORTED_LIGHT_THING_TYPES = Collections.singleton(THING_TYPE_MZ100); + public static final Set SUPPORTED_LIGHT_THING_TYPES = Set.of(THING_TYPE_MZ100); - public static final Set 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 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); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java index 75e5dd7f4..8a22a09b6 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java @@ -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 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> 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; diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoUtil.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoUtil.java index 22046a040..fa5bd4e34 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoUtil.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoUtil.java @@ -12,16 +12,13 @@ */ 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 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 buildBuiltinXMLEntityMap() { Map entities = new HashMap(10); entities.put("lt", "<"); diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBaseThingHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBaseThingHandler.java index ec11ee57b..1ce737d04 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBaseThingHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBaseThingHandler.java @@ -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 subscriptions = new ConcurrentHashMap(); 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 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; } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java index bd16e5bf4..3912223cc 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java index a2e76beea..efec9447b 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java index 846fecb9f..1eb0b75a0 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java index ae84e0806..40b74df37 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java index 5802c6c55..828069eda 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoInsightHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoInsightHandler.java index 19ad6e253..501966b12 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoInsightHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoInsightHandler.java @@ -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 diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java index 2956ea3c9..668280a53 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java index a94d378a4..1f29f9d9d 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java @@ -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()); } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMotionHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMotionHandler.java index f51bd09af..b591fd370 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMotionHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMotionHandler.java @@ -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 stateMap = new ConcurrentHashMap(); - 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 diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoSwitchHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoSwitchHandler.java index 99c6668ef..cd54b9823 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoSwitchHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoSwitchHandler.java @@ -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 stateMap = new ConcurrentHashMap(); - 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 diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/http/WemoHttpCall.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/http/WemoHttpCall.java index 30314d7cf..48524e954 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/http/WemoHttpCall.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/http/WemoHttpCall.java @@ -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; + } + } } diff --git a/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/handler/test/WemoInsightHandlerTest.java b/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/handler/test/WemoInsightHandlerTest.java index a54265398..1a2a86124 100644 --- a/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/handler/test/WemoInsightHandlerTest.java +++ b/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/handler/test/WemoInsightHandlerTest.java @@ -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; } diff --git a/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/test/GenericWemoOSGiTest.java b/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/test/GenericWemoOSGiTest.java index 98ffd9fdb..ad8e44052 100644 --- a/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/test/GenericWemoOSGiTest.java +++ b/itests/org.openhab.binding.wemo.tests/src/main/java/org/openhab/binding/wemo/internal/test/GenericWemoOSGiTest.java @@ -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());