[wemo] add annotations and remove usage of apache.commons.* (#9829)
* [wemo] add annotations and remove usage of apache.commons.* Also-by: Wouter Born <github@maindrain.net> Signed-off-by: Hans-Jörg Merk <github@hmerk.de>
This commit is contained in:
parent
8521756abb
commit
fdada9a155
|
@ -17,6 +17,7 @@ import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +27,7 @@ import org.openhab.core.thing.ThingTypeUID;
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
* @author Mihir Patil - Added standby switch
|
* @author Mihir Patil - Added standby switch
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoBindingConstants {
|
public class WemoBindingConstants {
|
||||||
|
|
||||||
public static final String BINDING_ID = "wemo";
|
public static final String BINDING_ID = "wemo";
|
||||||
|
@ -109,8 +111,8 @@ public class WemoBindingConstants {
|
||||||
public static final String UDN = "udn";
|
public static final String UDN = "udn";
|
||||||
public static final String DEVICE_ID = "deviceID";
|
public static final String DEVICE_ID = "deviceID";
|
||||||
public static final String POLLINGINTERVALL = "pollingInterval";
|
public static final String POLLINGINTERVALL = "pollingInterval";
|
||||||
|
public static final int DEFAULT_REFRESH_INTERVALL_SECONDS = 60;
|
||||||
public static final int SUBSCRIPTION_DURATION = 600;
|
public static final int SUBSCRIPTION_DURATION_SECONDS = 600;
|
||||||
public static final int LINK_DISCOVERY_SERVICE_INITIAL_DELAY = 5;
|
public static final int LINK_DISCOVERY_SERVICE_INITIAL_DELAY = 5;
|
||||||
public static final String HTTP_CALL_CONTENT_HEADER = "text/xml; charset=utf-8";
|
public static final String HTTP_CALL_CONTENT_HEADER = "text/xml; charset=utf-8";
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ import java.util.Hashtable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.discovery.WemoLinkDiscoveryService;
|
import org.openhab.binding.wemo.internal.discovery.WemoLinkDiscoveryService;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoCoffeeHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoCoffeeHandler;
|
||||||
|
@ -39,8 +41,11 @@ import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
import org.osgi.framework.ServiceRegistration;
|
import org.osgi.framework.ServiceRegistration;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -51,15 +56,17 @@ import org.slf4j.LoggerFactory;
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
* @author Kai Kreuzer - some refactoring for performance and simplification
|
* @author Kai Kreuzer - some refactoring for performance and simplification
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.wemo")
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.wemo")
|
||||||
public class WemoHandlerFactory extends BaseThingHandlerFactory {
|
public class WemoHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoHandlerFactory.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoHandlerFactory.class);
|
||||||
|
|
||||||
private UpnpIOService upnpIOService;
|
|
||||||
|
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = WemoBindingConstants.SUPPORTED_THING_TYPES;
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = WemoBindingConstants.SUPPORTED_THING_TYPES;
|
||||||
|
|
||||||
|
private UpnpIOService upnpIOService;
|
||||||
|
private @Nullable WemoHttpCallFactory wemoHttpCallFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||||
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
|
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
|
||||||
|
@ -67,70 +74,73 @@ public class WemoHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||||
|
|
||||||
@SuppressWarnings({ "null", "unused" })
|
@Activate
|
||||||
@Override
|
public WemoHandlerFactory(final @Reference UpnpIOService upnpIOService) {
|
||||||
protected ThingHandler createHandler(Thing thing) {
|
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
|
||||||
if (thingTypeUID != null) {
|
|
||||||
logger.debug("Trying to create a handler for ThingType '{}", thingTypeUID);
|
|
||||||
|
|
||||||
WemoHttpCall wemoHttpcaller = new WemoHttpCall();
|
|
||||||
|
|
||||||
if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_BRIDGE)) {
|
|
||||||
logger.debug("Creating a WemoBridgeHandler for thing '{}' with UDN '{}'", thing.getUID(),
|
|
||||||
thing.getConfiguration().get(UDN));
|
|
||||||
WemoBridgeHandler handler = new WemoBridgeHandler((Bridge) thing);
|
|
||||||
registerDeviceDiscoveryService(handler, wemoHttpcaller);
|
|
||||||
return handler;
|
|
||||||
} 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);
|
|
||||||
} else if (WemoBindingConstants.SUPPORTED_DEVICE_THING_TYPES.contains(thing.getThingTypeUID())) {
|
|
||||||
logger.debug("Creating a WemoHandler for thing '{}' with UDN '{}'", thing.getUID(),
|
|
||||||
thing.getConfiguration().get(UDN));
|
|
||||||
return new WemoHandler(thing, upnpIOService, 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);
|
|
||||||
} 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);
|
|
||||||
} 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);
|
|
||||||
} 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);
|
|
||||||
} 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);
|
|
||||||
} 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);
|
|
||||||
} else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_MZ100)) {
|
|
||||||
return new WemoLightHandler(thing, upnpIOService, wemoHttpcaller);
|
|
||||||
} else {
|
|
||||||
logger.warn("ThingHandler not found for {}", thingTypeUID);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Reference
|
|
||||||
protected void setUpnpIOService(UpnpIOService upnpIOService) {
|
|
||||||
this.upnpIOService = upnpIOService;
|
this.upnpIOService = upnpIOService;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void unsetUpnpIOService(UpnpIOService upnpIOService) {
|
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||||
this.upnpIOService = null;
|
public void setWemoHttpCallFactory(WemoHttpCallFactory wemoHttpCallFactory) {
|
||||||
|
this.wemoHttpCallFactory = wemoHttpCallFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsetWemoHttpCallFactory(WemoHttpCallFactory wemoHttpCallFactory) {
|
||||||
|
this.wemoHttpCallFactory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
|
logger.debug("Trying to create a handler for ThingType '{}", thingTypeUID);
|
||||||
|
|
||||||
|
WemoHttpCallFactory wemoHttpCallFactory = this.wemoHttpCallFactory;
|
||||||
|
WemoHttpCall wemoHttpcaller = wemoHttpCallFactory == null ? new WemoHttpCall()
|
||||||
|
: wemoHttpCallFactory.createHttpCall();
|
||||||
|
|
||||||
|
if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_BRIDGE)) {
|
||||||
|
logger.debug("Creating a WemoBridgeHandler for thing '{}' with UDN '{}'", thing.getUID(),
|
||||||
|
thing.getConfiguration().get(UDN));
|
||||||
|
WemoBridgeHandler handler = new WemoBridgeHandler((Bridge) thing);
|
||||||
|
registerDeviceDiscoveryService(handler, wemoHttpcaller);
|
||||||
|
return handler;
|
||||||
|
} 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);
|
||||||
|
} else if (WemoBindingConstants.SUPPORTED_DEVICE_THING_TYPES.contains(thing.getThingTypeUID())) {
|
||||||
|
logger.debug("Creating a WemoHandler for thing '{}' with UDN '{}'", thing.getUID(),
|
||||||
|
thing.getConfiguration().get(UDN));
|
||||||
|
return new WemoHandler(thing, upnpIOService, 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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} 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);
|
||||||
|
} else if (thingTypeUID.equals(WemoBindingConstants.THING_TYPE_MZ100)) {
|
||||||
|
return new WemoLightHandler(thing, upnpIOService, wemoHttpcaller);
|
||||||
|
} else {
|
||||||
|
logger.warn("ThingHandler not found for {}", thingTypeUID);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.wemo.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link WemoHttpCallFactory} creates {@WemoHttpCall}s.
|
||||||
|
*
|
||||||
|
* @author Wouter Born - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public interface WemoHttpCallFactory {
|
||||||
|
|
||||||
|
WemoHttpCall createHttpCall();
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.wemo.internal;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link WemoUtil} implements some helper functions.
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@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);
|
||||||
|
if (pos > 0) {
|
||||||
|
return string.substring(0, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String substringBetween(@Nullable String string, String begin, String end) {
|
||||||
|
if (string != null) {
|
||||||
|
int s = string.indexOf(begin);
|
||||||
|
if (s != -1) {
|
||||||
|
String result = string.substring(s + begin.length());
|
||||||
|
return substringBefore(result, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String unescape(final String text) {
|
||||||
|
StringBuilder result = new StringBuilder(text.length());
|
||||||
|
int i = 0;
|
||||||
|
int n = text.length();
|
||||||
|
while (i < n) {
|
||||||
|
char charAt = text.charAt(i);
|
||||||
|
if (charAt != '&') {
|
||||||
|
result.append(charAt);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
if (text.startsWith("&", i)) {
|
||||||
|
result.append('&');
|
||||||
|
i += 5;
|
||||||
|
} else if (text.startsWith("'", i)) {
|
||||||
|
result.append('\'');
|
||||||
|
i += 6;
|
||||||
|
} else if (text.startsWith(""", i)) {
|
||||||
|
result.append('"');
|
||||||
|
i += 6;
|
||||||
|
} else if (text.startsWith("<", i)) {
|
||||||
|
result.append('<');
|
||||||
|
i += 4;
|
||||||
|
} else if (text.startsWith(">", i)) {
|
||||||
|
result.append('>');
|
||||||
|
i += 4;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String unescapeXml(final String xml) {
|
||||||
|
Pattern xmlEntityRegex = Pattern.compile("&(#?)([^;]+);");
|
||||||
|
// Unfortunately, Matcher requires a StringBuffer instead of a StringBuilder
|
||||||
|
StringBuffer unescapedOutput = new StringBuffer(xml.length());
|
||||||
|
|
||||||
|
Matcher m = xmlEntityRegex.matcher(xml);
|
||||||
|
Map<String, String> builtinEntities = null;
|
||||||
|
String entity;
|
||||||
|
String hashmark;
|
||||||
|
String ent;
|
||||||
|
int code;
|
||||||
|
while (m.find()) {
|
||||||
|
ent = m.group(2);
|
||||||
|
hashmark = m.group(1);
|
||||||
|
if ((hashmark != null) && (hashmark.length() > 0)) {
|
||||||
|
code = Integer.parseInt(ent);
|
||||||
|
entity = Character.toString((char) code);
|
||||||
|
} else {
|
||||||
|
// must be a non-numerical entity
|
||||||
|
if (builtinEntities == null) {
|
||||||
|
builtinEntities = buildBuiltinXMLEntityMap();
|
||||||
|
}
|
||||||
|
entity = builtinEntities.get(ent);
|
||||||
|
if (entity == null) {
|
||||||
|
// not a known entity - ignore it
|
||||||
|
entity = "&" + ent + ';';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.appendReplacement(unescapedOutput, entity);
|
||||||
|
}
|
||||||
|
m.appendTail(unescapedOutput);
|
||||||
|
|
||||||
|
return unescapedOutput.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable String getWemoURL(URL descriptorURL, String actionService) {
|
||||||
|
int portCheckStart = 49151;
|
||||||
|
int portCheckStop = 49157;
|
||||||
|
String port = null;
|
||||||
|
String host = substringBetween(descriptorURL.toString(), "://", ":");
|
||||||
|
for (int i = portCheckStart; i < portCheckStop; i++) {
|
||||||
|
if (serviceAvailableFunction.apply(host, i)) {
|
||||||
|
port = String.valueOf(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return port == null ? null : "http://" + host + ":" + port + "/upnp/control/" + actionService + "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
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", "<");
|
||||||
|
entities.put("gt", ">");
|
||||||
|
entities.put("amp", "&");
|
||||||
|
entities.put("apos", "'");
|
||||||
|
entities.put("quot", "\"");
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.jupnp.model.meta.RemoteDevice;
|
import org.jupnp.model.meta.RemoteDevice;
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
|
@ -39,6 +40,7 @@ import org.slf4j.LoggerFactory;
|
||||||
* @author Kai Kreuzer - some refactoring for performance and simplification
|
* @author Kai Kreuzer - some refactoring for performance and simplification
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = UpnpDiscoveryParticipant.class)
|
@Component(service = UpnpDiscoveryParticipant.class)
|
||||||
public class WemoDiscoveryParticipant implements UpnpDiscoveryParticipant {
|
public class WemoDiscoveryParticipant implements UpnpDiscoveryParticipant {
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ public class WemoDiscoveryParticipant implements UpnpDiscoveryParticipant {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiscoveryResult createResult(RemoteDevice device) {
|
public @Nullable DiscoveryResult createResult(RemoteDevice device) {
|
||||||
ThingUID uid = getThingUID(device);
|
ThingUID uid = getThingUID(device);
|
||||||
if (uid != null) {
|
if (uid != null) {
|
||||||
Map<String, Object> properties = new HashMap<>(2);
|
Map<String, Object> properties = new HashMap<>(2);
|
||||||
|
@ -75,7 +77,7 @@ public class WemoDiscoveryParticipant implements UpnpDiscoveryParticipant {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThingUID getThingUID(@Nullable RemoteDevice device) {
|
public @Nullable ThingUID getThingUID(@Nullable RemoteDevice device) {
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
if (device.getDetails().getManufacturerDetails().getManufacturer() != null) {
|
if (device.getDetails().getManufacturerDetails().getManufacturer() != null) {
|
||||||
if (device.getDetails().getManufacturerDetails().getManufacturer().toUpperCase().contains("BELKIN")) {
|
if (device.getDetails().getManufacturerDetails().getManufacturer().toUpperCase().contains("BELKIN")) {
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.wemo.internal.discovery;
|
package org.openhab.binding.wemo.internal.discovery;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.jupnp.UpnpService;
|
import org.jupnp.UpnpService;
|
||||||
import org.jupnp.model.message.header.RootDeviceHeader;
|
import org.jupnp.model.message.header.RootDeviceHeader;
|
||||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
@ -28,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
@Component(service = DiscoveryService.class, configurationPid = "discovery.wemo")
|
@Component(service = DiscoveryService.class, configurationPid = "discovery.wemo")
|
||||||
public class WemoDiscoveryService extends AbstractDiscoveryService {
|
public class WemoDiscoveryService extends AbstractDiscoveryService {
|
||||||
|
|
||||||
|
@ -37,7 +40,7 @@ public class WemoDiscoveryService extends AbstractDiscoveryService {
|
||||||
super(5);
|
super(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpnpService upnpService;
|
private @Nullable UpnpService upnpService;
|
||||||
|
|
||||||
@Reference
|
@Reference
|
||||||
protected void setUpnpService(UpnpService upnpService) {
|
protected void setUpnpService(UpnpService upnpService) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.discovery;
|
package org.openhab.binding.wemo.internal.discovery;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -26,8 +27,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
@ -53,6 +54,7 @@ import org.xml.sax.InputSource;
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoLinkDiscoveryService extends AbstractDiscoveryService implements UpnpIOParticipant {
|
public class WemoLinkDiscoveryService extends AbstractDiscoveryService implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoLinkDiscoveryService.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoLinkDiscoveryService.class);
|
||||||
|
@ -84,7 +86,7 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
/**
|
/**
|
||||||
* Schedule for scanning
|
* Schedule for scanning
|
||||||
*/
|
*/
|
||||||
private ScheduledFuture<?> scanningJob;
|
private @Nullable ScheduledFuture<?> scanningJob;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Upnp service
|
* The Upnp service
|
||||||
|
@ -96,20 +98,12 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
public WemoLinkDiscoveryService(WemoBridgeHandler wemoBridgeHandler, UpnpIOService upnpIOService,
|
public WemoLinkDiscoveryService(WemoBridgeHandler wemoBridgeHandler, UpnpIOService upnpIOService,
|
||||||
WemoHttpCall wemoHttpCaller) {
|
WemoHttpCall wemoHttpCaller) {
|
||||||
super(SEARCH_TIME);
|
super(SEARCH_TIME);
|
||||||
|
this.service = upnpIOService;
|
||||||
this.wemoBridgeHandler = wemoBridgeHandler;
|
this.wemoBridgeHandler = wemoBridgeHandler;
|
||||||
|
|
||||||
this.wemoHttpCaller = wemoHttpCaller;
|
this.wemoHttpCaller = wemoHttpCaller;
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scanningRunnable = new WemoLinkScan();
|
this.scanningRunnable = new WemoLinkScan();
|
||||||
if (wemoBridgeHandler == null) {
|
|
||||||
logger.warn("no bridge handler for scan given");
|
|
||||||
}
|
|
||||||
this.activate(null);
|
this.activate(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +128,7 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
|
||||||
if (descriptorURL != null) {
|
if (descriptorURL != null) {
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
String deviceURL = substringBefore(descriptorURL.toString(), "/setup.xml");
|
||||||
String wemoURL = deviceURL + "/upnp/control/bridge1";
|
String wemoURL = deviceURL + "/upnp/control/bridge1";
|
||||||
|
|
||||||
String endDeviceRequest = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String endDeviceRequest = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||||
|
@ -143,10 +137,9 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
logger.trace("endDeviceRequest answered '{}'", endDeviceRequest);
|
logger.trace("endDeviceRequest answered '{}'", endDeviceRequest);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String stringParser = StringUtils.substringBetween(endDeviceRequest, "<DeviceLists>",
|
String stringParser = substringBetween(endDeviceRequest, "<DeviceLists>", "</DeviceLists>");
|
||||||
"</DeviceLists>");
|
|
||||||
|
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
|
|
||||||
// check if there are already paired devices with WeMo Link
|
// check if there are already paired devices with WeMo Link
|
||||||
if ("0".equals(stringParser)) {
|
if ("0".equals(stringParser)) {
|
||||||
|
@ -245,7 +238,9 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
protected void startBackgroundDiscovery() {
|
protected void startBackgroundDiscovery() {
|
||||||
logger.trace("Start WeMo device background discovery");
|
logger.trace("Start WeMo device background discovery");
|
||||||
|
|
||||||
if (scanningJob == null || scanningJob.isCancelled()) {
|
ScheduledFuture<?> job = scanningJob;
|
||||||
|
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
this.scanningJob = scheduler.scheduleWithFixedDelay(this.scanningRunnable,
|
this.scanningJob = scheduler.scheduleWithFixedDelay(this.scanningRunnable,
|
||||||
LINK_DISCOVERY_SERVICE_INITIAL_DELAY, SCAN_INTERVAL, TimeUnit.SECONDS);
|
LINK_DISCOVERY_SERVICE_INITIAL_DELAY, SCAN_INTERVAL, TimeUnit.SECONDS);
|
||||||
} else {
|
} else {
|
||||||
|
@ -257,10 +252,11 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
protected void stopBackgroundDiscovery() {
|
protected void stopBackgroundDiscovery() {
|
||||||
logger.debug("Stop WeMo device background discovery");
|
logger.debug("Stop WeMo device background discovery");
|
||||||
|
|
||||||
if (scanningJob != null && !scanningJob.isCancelled()) {
|
ScheduledFuture<?> job = scanningJob;
|
||||||
scanningJob.cancel(true);
|
if (job != null && !job.isCancelled()) {
|
||||||
scanningJob = null;
|
job.cancel(true);
|
||||||
}
|
}
|
||||||
|
scanningJob = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -269,11 +265,11 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,24 +12,21 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @author Stefan Triller - Initial contribution
|
||||||
* @author Stefan Triller
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public abstract class AbstractWemoHandler extends BaseThingHandler {
|
public abstract class AbstractWemoHandler extends BaseThingHandler {
|
||||||
|
|
||||||
public AbstractWemoHandler(Thing thing) {
|
|
||||||
super(thing);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected WemoHttpCall wemoHttpCaller;
|
protected WemoHttpCall wemoHttpCaller;
|
||||||
|
|
||||||
public void setWemoHttpCaller(WemoHttpCall wemoHttpCaller) {
|
public AbstractWemoHandler(Thing thing, WemoHttpCall wemoHttpCaller) {
|
||||||
|
super(thing);
|
||||||
this.wemoHttpCaller = wemoHttpCaller;
|
this.wemoHttpCaller = wemoHttpCaller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
@ -34,6 +35,7 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoBridgeHandler extends BaseBridgeHandler {
|
public class WemoBridgeHandler extends BaseBridgeHandler {
|
||||||
|
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
@ -30,8 +31,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -64,7 +65,7 @@ import org.xml.sax.InputSource;
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
|
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoCoffeeHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoCoffeeHandler.class);
|
||||||
|
@ -73,16 +74,11 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
|
|
||||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||||
|
|
||||||
protected static final int SUBSCRIPTION_DURATION = 600;
|
|
||||||
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
|
||||||
/**
|
private WemoHttpCall wemoCall;
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private final int REFRESH_INTERVAL = 60;
|
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
|
||||||
private final Runnable refreshRunnable = new Runnable() {
|
private final Runnable refreshRunnable = new Runnable() {
|
||||||
|
|
||||||
|
@ -102,18 +98,13 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
|
public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpCaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemoHttpcaller;
|
this.wemoCall = wemoHttpCaller;
|
||||||
|
this.service = upnpIOService;
|
||||||
|
|
||||||
logger.debug("Creating a WemoCoffeeHandler V0.4 for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoCoffeeHandler V0.4 for thing '{}'", getThing().getUID());
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,12 +125,12 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoCoffeeHandler disposed.");
|
logger.debug("WeMoCoffeeHandler disposed.");
|
||||||
|
|
||||||
removeSubscription();
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
job.cancel(true);
|
||||||
refreshJob.cancel(true);
|
|
||||||
refreshJob = null;
|
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -171,10 +162,11 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<attribute><name>Cleaning</name><value>NULL</value></attribute></attributeList>"
|
+ "<attribute><name>Cleaning</name><value>NULL</value></attribute></attributeList>"
|
||||||
+ "</u:SetAttributes>" + "</s:Body>" + "</s:Envelope>";
|
+ "</u:SetAttributes>" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
String wemoURL = getWemoURL("deviceevent");
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
updateState(CHANNEL_STATE, OnOffType.ON);
|
updateState(CHANNEL_STATE, OnOffType.ON);
|
||||||
State newMode = new StringType("Brewing");
|
State newMode = new StringType("Brewing");
|
||||||
|
@ -195,13 +187,16 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
|
if (service != null) {
|
||||||
subscriptionState.put(service, succeeded);
|
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
|
||||||
|
succeeded ? "succeeded" : "failed");
|
||||||
|
subscriptionState.put(service, succeeded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
// We can subscribe to GENA events, but there is no usefull response right now.
|
// We can subscribe to GENA events, but there is no usefull response right now.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +205,9 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
||||||
|
|
||||||
String subscription = "deviceevent1";
|
String subscription = "deviceevent1";
|
||||||
if ((subscriptionState.get(subscription) == null) || !subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -226,7 +221,7 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
|
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
String subscription = "deviceevent1";
|
String subscription = "deviceevent1";
|
||||||
if ((subscriptionState.get(subscription) != null) && subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
@ -237,9 +232,10 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = REFRESH_INTERVAL;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("pollingInterval");
|
Object refreshConfig = config.get("pollingInterval");
|
||||||
if (refreshConfig != null) {
|
if (refreshConfig != null) {
|
||||||
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
||||||
|
@ -272,17 +268,18 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, actionService);
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
try {
|
try {
|
||||||
String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
|
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||||
"</attributeList>");
|
|
||||||
|
|
||||||
// Due to Belkins bad response formatting, we need to run this twice.
|
// Due to Belkins bad response formatting, we need to run this twice.
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
|
|
||||||
logger.trace("CoffeeMaker response '{}' for device '{}' received", stringParser,
|
logger.trace("CoffeeMaker response '{}' for device '{}' received", stringParser,
|
||||||
getThing().getUID());
|
getThing().getUID());
|
||||||
|
@ -321,6 +318,8 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
switch (attributeName) {
|
switch (attributeName) {
|
||||||
case "Mode":
|
case "Mode":
|
||||||
State newMode = new StringType("Brewing");
|
State newMode = new StringType("Brewing");
|
||||||
|
State newAttributeValue;
|
||||||
|
|
||||||
switch (attributeValue) {
|
switch (attributeValue) {
|
||||||
case "0":
|
case "0":
|
||||||
updateState(CHANNEL_STATE, OnOffType.ON);
|
updateState(CHANNEL_STATE, OnOffType.ON);
|
||||||
|
@ -370,51 +369,35 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "ModeTime":
|
case "ModeTime":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = new DecimalType(attributeValue);
|
||||||
State newAttributeValue = new DecimalType(attributeValue);
|
updateState(CHANNEL_MODETIME, newAttributeValue);
|
||||||
updateState(CHANNEL_MODETIME, newAttributeValue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "TimeRemaining":
|
case "TimeRemaining":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = new DecimalType(attributeValue);
|
||||||
State newAttributeValue = new DecimalType(attributeValue);
|
updateState(CHANNEL_TIMEREMAINING, newAttributeValue);
|
||||||
updateState(CHANNEL_TIMEREMAINING, newAttributeValue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "WaterLevelReached":
|
case "WaterLevelReached":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = new DecimalType(attributeValue);
|
||||||
State newAttributeValue = new DecimalType(attributeValue);
|
updateState(CHANNEL_WATERLEVELREACHED, newAttributeValue);
|
||||||
updateState(CHANNEL_WATERLEVELREACHED, newAttributeValue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "CleanAdvise":
|
case "CleanAdvise":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
State newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF
|
updateState(CHANNEL_CLEANADVISE, newAttributeValue);
|
||||||
: OnOffType.ON;
|
|
||||||
updateState(CHANNEL_CLEANADVISE, newAttributeValue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "FilterAdvise":
|
case "FilterAdvise":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
State newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF
|
updateState(CHANNEL_FILTERADVISE, newAttributeValue);
|
||||||
: OnOffType.ON;
|
|
||||||
updateState(CHANNEL_FILTERADVISE, newAttributeValue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "Brewed":
|
case "Brewed":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = getDateTimeState(attributeValue);
|
||||||
State newAttributeValue = getDateTimeState(attributeValue);
|
if (newAttributeValue != null) {
|
||||||
if (newAttributeValue != null) {
|
updateState(CHANNEL_BREWED, newAttributeValue);
|
||||||
updateState(CHANNEL_BREWED, newAttributeValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "LastCleaned":
|
case "LastCleaned":
|
||||||
if (attributeValue != null) {
|
newAttributeValue = getDateTimeState(attributeValue);
|
||||||
State newAttributeValue = getDateTimeState(attributeValue);
|
if (newAttributeValue != null) {
|
||||||
if (newAttributeValue != null) {
|
updateState(CHANNEL_LASTCLEANED, newAttributeValue);
|
||||||
updateState(CHANNEL_LASTCLEANED, newAttributeValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -430,37 +413,19 @@ public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
public @Nullable State getDateTimeState(String attributeValue) {
|
||||||
public State getDateTimeState(String attributeValue) {
|
long value = 0;
|
||||||
if (attributeValue != null) {
|
try {
|
||||||
long value = 0;
|
value = Long.parseLong(attributeValue);
|
||||||
try {
|
} catch (NumberFormatException e) {
|
||||||
value = Long.parseLong(attributeValue) * 1000; // convert s to ms
|
logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||||
} catch (NumberFormatException e) {
|
getThing().getUID());
|
||||||
logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
return null;
|
||||||
getThing().getUID());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(value),
|
|
||||||
TimeZone.getDefault().toZoneId());
|
|
||||||
State dateTimeState = new DateTimeType(zoned);
|
|
||||||
if (dateTimeState != null) {
|
|
||||||
logger.trace("New attribute brewed '{}' received", dateTimeState);
|
|
||||||
return dateTimeState;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochSecond(value), TimeZone.getDefault().toZoneId());
|
||||||
}
|
State dateTimeState = new DateTimeType(zoned);
|
||||||
|
logger.trace("New attribute brewed '{}' received", dateTimeState);
|
||||||
public String getWemoURL(String actionService) {
|
return dateTimeState;
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
String wemoURL = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
|
||||||
wemoURL = deviceURL + "/upnp/control/" + actionService + "1";
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCharacterDataFromElement(Element e) {
|
public static String getCharacterDataFromElement(Element e) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -23,7 +24,8 @@ import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -47,22 +49,21 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution;
|
* @author Hans-Jörg Merk - Initial contribution;
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoCrockpotHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoCrockpotHandler.class);
|
||||||
|
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_CROCKPOT);
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_CROCKPOT);
|
||||||
/**
|
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private static final int DEFAULT_REFRESH_INTERVAL_SECONDS = 120;
|
|
||||||
private final Map<String, Boolean> subscriptionState = new HashMap<>();
|
private final Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
|
||||||
private final Runnable refreshRunnable = () -> {
|
private final Runnable refreshRunnable = () -> {
|
||||||
updateWemoState();
|
updateWemoState();
|
||||||
|
@ -73,18 +74,13 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
|
public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpCaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemohttpCaller;
|
this.wemoCall = wemoHttpCaller;
|
||||||
|
this.service = upnpIOService;
|
||||||
|
|
||||||
logger.debug("Creating a WemoCrockpotHandler for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoCrockpotHandler for thing '{}'", getThing().getUID());
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -106,12 +102,12 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoCrockpotHandler disposed.");
|
logger.debug("WeMoCrockpotHandler disposed.");
|
||||||
|
|
||||||
removeSubscription();
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
job.cancel(true);
|
||||||
refreshJob.cancel(true);
|
|
||||||
refreshJob = null;
|
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -146,10 +142,12 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
+ "<s:Body>" + "<u:SetCrockpotState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<mode>"
|
+ "<s:Body>" + "<u:SetCrockpotState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<mode>"
|
||||||
+ mode + "</mode>" + "<time>" + time + "</time>" + "</u:SetCrockpotState>" + "</s:Body>"
|
+ mode + "</mode>" + "<time>" + time + "</time>" + "</u:SetCrockpotState>" + "</s:Body>"
|
||||||
+ "</s:Envelope>";
|
+ "</s:Envelope>";
|
||||||
String wemoURL = getWemoURL("basicevent");
|
|
||||||
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
||||||
|
@ -160,18 +158,23 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
|
if (service != null) {
|
||||||
subscriptionState.put(service, succeeded);
|
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
|
||||||
|
succeeded ? "succeeded" : "failed");
|
||||||
|
subscriptionState.put(service, succeeded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'", variable, value, service,
|
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'", variable, value, service,
|
||||||
this.getThing().getUID());
|
this.getThing().getUID());
|
||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
this.stateMap.put(variable, value);
|
if (variable != null && value != null) {
|
||||||
|
this.stateMap.put(variable, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onSubscription() {
|
private synchronized void onSubscription() {
|
||||||
|
@ -180,9 +183,9 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
|
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) == null) || !subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +201,7 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) != null) && subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
@ -209,11 +212,12 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL_SECONDS;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVAL_SECONDS
|
refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVALL_SECONDS
|
||||||
: ((BigDecimal) refreshConfig).intValue();
|
: ((BigDecimal) refreshConfig).intValue();
|
||||||
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
@ -244,42 +248,41 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, actionService);
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
||||||
String mode = StringUtils.substringBetween(wemoCallResponse, "<mode>", "</mode>");
|
String mode = substringBetween(wemoCallResponse, "<mode>", "</mode>");
|
||||||
String time = StringUtils.substringBetween(wemoCallResponse, "<time>", "</time>");
|
String time = substringBetween(wemoCallResponse, "<time>", "</time>");
|
||||||
String coockedTime = StringUtils.substringBetween(wemoCallResponse, "<coockedTime>",
|
String coockedTime = substringBetween(wemoCallResponse, "<coockedTime>", "</coockedTime>");
|
||||||
"</coockedTime>");
|
|
||||||
|
|
||||||
if (mode != null && time != null && coockedTime != null) {
|
State newMode = new StringType(mode);
|
||||||
State newMode = new StringType(mode);
|
State newCoockedTime = DecimalType.valueOf(coockedTime);
|
||||||
State newCoockedTime = DecimalType.valueOf(coockedTime);
|
switch (mode) {
|
||||||
switch (mode) {
|
case "0":
|
||||||
case "0":
|
newMode = new StringType("OFF");
|
||||||
newMode = new StringType("OFF");
|
break;
|
||||||
break;
|
case "50":
|
||||||
case "50":
|
newMode = new StringType("WARM");
|
||||||
newMode = new StringType("WARM");
|
State warmTime = DecimalType.valueOf(time);
|
||||||
State warmTime = DecimalType.valueOf(time);
|
updateState(CHANNEL_WARMCOOKTIME, warmTime);
|
||||||
updateState(CHANNEL_WARMCOOKTIME, warmTime);
|
break;
|
||||||
break;
|
case "51":
|
||||||
case "51":
|
newMode = new StringType("LOW");
|
||||||
newMode = new StringType("LOW");
|
State lowTime = DecimalType.valueOf(time);
|
||||||
State lowTime = DecimalType.valueOf(time);
|
updateState(CHANNEL_LOWCOOKTIME, lowTime);
|
||||||
updateState(CHANNEL_LOWCOOKTIME, lowTime);
|
break;
|
||||||
break;
|
case "52":
|
||||||
case "52":
|
newMode = new StringType("HIGH");
|
||||||
newMode = new StringType("HIGH");
|
State highTime = DecimalType.valueOf(time);
|
||||||
State highTime = DecimalType.valueOf(time);
|
updateState(CHANNEL_HIGHCOOKTIME, highTime);
|
||||||
updateState(CHANNEL_HIGHCOOKTIME, highTime);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
updateState(CHANNEL_COOKMODE, newMode);
|
|
||||||
updateState(CHANNEL_COOKEDTIME, newCoockedTime);
|
|
||||||
}
|
}
|
||||||
|
updateState(CHANNEL_COOKMODE, newMode);
|
||||||
|
updateState(CHANNEL_COOKEDTIME, newCoockedTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -289,17 +292,6 @@ public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOPa
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL(String actionService) {
|
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
String wemoURL = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
|
||||||
wemoURL = deviceURL + "/upnp/control/" + actionService + "1";
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChanged(boolean status) {
|
public void onStatusChanged(boolean status) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -26,7 +27,8 @@ import java.util.TimeZone;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -53,27 +55,28 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoDimmerHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoDimmerHandler.class);
|
||||||
|
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DIMMER);
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DIMMER);
|
||||||
|
|
||||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||||
private Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
private Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
protected static final int SUBSCRIPTION_DURATION = 600;
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
private int currentBrightness;
|
private int currentBrightness;
|
||||||
private int currentNightModeBrightness;
|
private int currentNightModeBrightness;
|
||||||
private String currentNightModeState = null;
|
private @Nullable String currentNightModeState;
|
||||||
/**
|
/**
|
||||||
* Set dimming stepsize to 5%
|
* Set dimming stepsize to 5%
|
||||||
*/
|
*/
|
||||||
private static final int DIM_STEPSIZE = 5;
|
private static final int DIM_STEPSIZE = 5;
|
||||||
/**
|
|
||||||
* The default refresh interval in Seconds.
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
*/
|
|
||||||
private int DEFAULT_REFRESH_INTERVAL = 60;
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
|
||||||
private Runnable refreshRunnable = new Runnable() {
|
private Runnable refreshRunnable = new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -90,15 +93,13 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
|
public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpCaller);
|
||||||
this.wemoHttpCaller = wemohttpCaller;
|
|
||||||
|
this.service = upnpIOService;
|
||||||
|
this.wemoCall = wemoHttpCaller;
|
||||||
|
|
||||||
logger.debug("Creating a WemoDimmerHandler for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoDimmerHandler for thing '{}'", getThing().getUID());
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,11 +118,14 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoDimmerHandler disposed.");
|
logger.debug("WeMoDimmerHandler disposed.");
|
||||||
removeSubscription();
|
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
refreshJob.cancel(true);
|
if (job != null && !job.isCancelled()) {
|
||||||
refreshJob = null;
|
job.cancel(true);
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -140,6 +144,7 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
String timeStamp = null;
|
String timeStamp = null;
|
||||||
switch (channelUID.getId()) {
|
switch (channelUID.getId()) {
|
||||||
case CHANNEL_BRIGHTNESS:
|
case CHANNEL_BRIGHTNESS:
|
||||||
|
String binaryState = this.stateMap.get("BinaryState");
|
||||||
if (command instanceof OnOffType) {
|
if (command instanceof OnOffType) {
|
||||||
value = command.equals(OnOffType.OFF) ? "0" : "1";
|
value = command.equals(OnOffType.OFF) ? "0" : "1";
|
||||||
setBinaryState(action, argument, value);
|
setBinaryState(action, argument, value);
|
||||||
|
@ -163,7 +168,7 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
value = "0";
|
value = "0";
|
||||||
argument = "BinaryState";
|
argument = "BinaryState";
|
||||||
setBinaryState(action, argument, "0");
|
setBinaryState(action, argument, "0");
|
||||||
} else if (this.stateMap.get("BinaryState").equals("0")) {
|
} else if ("0".equals(binaryState)) {
|
||||||
argument = "BinaryState";
|
argument = "BinaryState";
|
||||||
setBinaryState(action, argument, "1");
|
setBinaryState(action, argument, "1");
|
||||||
}
|
}
|
||||||
|
@ -197,7 +202,7 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
value = "0";
|
value = "0";
|
||||||
argument = "BinaryState";
|
argument = "BinaryState";
|
||||||
setBinaryState(action, argument, "0");
|
setBinaryState(action, argument, "0");
|
||||||
} else if (this.stateMap.get("BinaryState").equals("0")) {
|
} else if ("0".equals(binaryState)) {
|
||||||
argument = "BinaryState";
|
argument = "BinaryState";
|
||||||
setBinaryState(action, argument, "1");
|
setBinaryState(action, argument, "1");
|
||||||
}
|
}
|
||||||
|
@ -235,12 +240,15 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
logger.info("timestamp '{}' created", timeStamp);
|
logger.info("timestamp '{}' created", timeStamp);
|
||||||
String faderSeconds = null;
|
String faderSeconds = null;
|
||||||
String faderEnabled = null;
|
String faderEnabled = null;
|
||||||
String[] splitFader = this.stateMap.get("fader").split(":");
|
String fader = this.stateMap.get("fader");
|
||||||
if (splitFader[0] != null) {
|
if (fader != null) {
|
||||||
faderSeconds = splitFader[0];
|
String[] splitFader = fader.split(":");
|
||||||
}
|
if (splitFader[0] != null) {
|
||||||
if (splitFader[0] != null) {
|
faderSeconds = splitFader[0];
|
||||||
faderEnabled = splitFader[2];
|
}
|
||||||
|
if (splitFader[0] != null) {
|
||||||
|
faderEnabled = splitFader[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (faderSeconds != null && faderEnabled != null) {
|
if (faderSeconds != null && faderEnabled != null) {
|
||||||
if (command.equals(OnOffType.ON)) {
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
@ -311,82 +319,100 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
|
if (service != null) {
|
||||||
subscriptionState.put(service, succeeded);
|
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
|
||||||
|
succeeded ? "succeeded" : "failed");
|
||||||
|
subscriptionState.put(service, succeeded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
||||||
new Object[] { variable, value, service, this.getThing().getUID() });
|
new Object[] { variable, value, service, this.getThing().getUID() });
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
this.stateMap.put(variable, value);
|
if (variable != null && value != null) {
|
||||||
switch (variable) {
|
this.stateMap.put(variable, value);
|
||||||
case "BinaryState":
|
}
|
||||||
State state = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
if (variable != null && value != null) {
|
||||||
logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
|
switch (variable) {
|
||||||
updateState(CHANNEL_BRIGHTNESS, state);
|
case "BinaryState":
|
||||||
if (state.equals(OnOffType.OFF)) {
|
State state = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
updateState(CHANNEL_TIMERSTART, OnOffType.OFF);
|
logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
|
||||||
}
|
updateState(CHANNEL_BRIGHTNESS, state);
|
||||||
break;
|
if (state.equals(OnOffType.OFF)) {
|
||||||
case "brightness":
|
updateState(CHANNEL_TIMERSTART, OnOffType.OFF);
|
||||||
logger.debug("brightness '{}' for device '{}' received", value, getThing().getUID());
|
|
||||||
int newBrightnessValue = Integer.valueOf(value);
|
|
||||||
State newBrightnessState = new PercentType(newBrightnessValue);
|
|
||||||
if (this.stateMap.get("BinaryState").equals("1")) {
|
|
||||||
updateState(CHANNEL_BRIGHTNESS, newBrightnessState);
|
|
||||||
}
|
|
||||||
currentBrightness = newBrightnessValue;
|
|
||||||
break;
|
|
||||||
case "fader":
|
|
||||||
logger.debug("fader '{}' for device '{}' received", value, getThing().getUID());
|
|
||||||
String[] splitFader = value.split(":");
|
|
||||||
if (splitFader[0] != null) {
|
|
||||||
int faderSeconds = Integer.valueOf(splitFader[0]);
|
|
||||||
State faderMinutes = new DecimalType(faderSeconds / 60);
|
|
||||||
logger.debug("faderTime '{} minutes' for device '{}' received", faderMinutes, getThing().getUID());
|
|
||||||
updateState(CHANNEL_FADERCOUNTDOWNTIME, faderMinutes);
|
|
||||||
}
|
|
||||||
if (splitFader[1] != null) {
|
|
||||||
State isTimerRunning = splitFader[1].equals("-1") ? OnOffType.OFF : OnOffType.ON;
|
|
||||||
logger.debug("isTimerRunning '{}' for device '{}' received", isTimerRunning, getThing().getUID());
|
|
||||||
updateState(CHANNEL_TIMERSTART, isTimerRunning);
|
|
||||||
if (isTimerRunning.equals(OnOffType.ON)) {
|
|
||||||
updateState(CHANNEL_STATE, OnOffType.ON);
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
if (splitFader[2] != null) {
|
case "brightness":
|
||||||
State isFaderEnabled = splitFader[1].equals("0") ? OnOffType.OFF : OnOffType.ON;
|
logger.debug("brightness '{}' for device '{}' received", value, getThing().getUID());
|
||||||
logger.debug("isFaderEnabled '{}' for device '{}' received", isFaderEnabled, getThing().getUID());
|
int newBrightnessValue = Integer.valueOf(value);
|
||||||
updateState(CHANNEL_FADERENABLED, isFaderEnabled);
|
State newBrightnessState = new PercentType(newBrightnessValue);
|
||||||
}
|
String binaryState = this.stateMap.get("BinaryState");
|
||||||
break;
|
if (binaryState != null) {
|
||||||
case "nightMode":
|
if (binaryState.equals("1")) {
|
||||||
State nightModeState = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
updateState(CHANNEL_BRIGHTNESS, newBrightnessState);
|
||||||
currentNightModeState = value;
|
}
|
||||||
logger.debug("nightModeState '{}' for device '{}' received", nightModeState, getThing().getUID());
|
}
|
||||||
updateState(CHANNEL_NIGHTMODE, nightModeState);
|
currentBrightness = newBrightnessValue;
|
||||||
break;
|
break;
|
||||||
case "startTime":
|
case "fader":
|
||||||
State startTimeState = getDateTimeState(value);
|
logger.debug("fader '{}' for device '{}' received", value, getThing().getUID());
|
||||||
logger.debug("startTimeState '{}' for device '{}' received", startTimeState, getThing().getUID());
|
String[] splitFader = value.split(":");
|
||||||
updateState(CHANNEL_STARTTIME, startTimeState);
|
if (splitFader[0] != null) {
|
||||||
break;
|
int faderSeconds = Integer.valueOf(splitFader[0]);
|
||||||
case "endTime":
|
State faderMinutes = new DecimalType(faderSeconds / 60);
|
||||||
State endTimeState = getDateTimeState(value);
|
logger.debug("faderTime '{} minutes' for device '{}' received", faderMinutes,
|
||||||
logger.debug("endTimeState '{}' for device '{}' received", endTimeState, getThing().getUID());
|
getThing().getUID());
|
||||||
updateState(CHANNEL_ENDTIME, endTimeState);
|
updateState(CHANNEL_FADERCOUNTDOWNTIME, faderMinutes);
|
||||||
break;
|
}
|
||||||
case "nightModeBrightness":
|
if (splitFader[1] != null) {
|
||||||
int nightModeBrightnessValue = Integer.valueOf(value);
|
State isTimerRunning = splitFader[1].equals("-1") ? OnOffType.OFF : OnOffType.ON;
|
||||||
currentNightModeBrightness = nightModeBrightnessValue;
|
logger.debug("isTimerRunning '{}' for device '{}' received", isTimerRunning,
|
||||||
State nightModeBrightnessState = new PercentType(nightModeBrightnessValue);
|
getThing().getUID());
|
||||||
logger.debug("nightModeBrightnessState '{}' for device '{}' received", nightModeBrightnessState,
|
updateState(CHANNEL_TIMERSTART, isTimerRunning);
|
||||||
getThing().getUID());
|
if (isTimerRunning.equals(OnOffType.ON)) {
|
||||||
updateState(CHANNEL_NIGHTMODEBRIGHTNESS, nightModeBrightnessState);
|
updateState(CHANNEL_STATE, OnOffType.ON);
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
if (splitFader[2] != null) {
|
||||||
|
State isFaderEnabled = splitFader[1].equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
|
logger.debug("isFaderEnabled '{}' for device '{}' received", isFaderEnabled,
|
||||||
|
getThing().getUID());
|
||||||
|
updateState(CHANNEL_FADERENABLED, isFaderEnabled);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "nightMode":
|
||||||
|
State nightModeState = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
|
currentNightModeState = value;
|
||||||
|
logger.debug("nightModeState '{}' for device '{}' received", nightModeState, getThing().getUID());
|
||||||
|
updateState(CHANNEL_NIGHTMODE, nightModeState);
|
||||||
|
break;
|
||||||
|
case "startTime":
|
||||||
|
State startTimeState = getDateTimeState(value);
|
||||||
|
logger.debug("startTimeState '{}' for device '{}' received", startTimeState, getThing().getUID());
|
||||||
|
if (startTimeState != null) {
|
||||||
|
updateState(CHANNEL_STARTTIME, startTimeState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "endTime":
|
||||||
|
State endTimeState = getDateTimeState(value);
|
||||||
|
logger.debug("endTimeState '{}' for device '{}' received", endTimeState, getThing().getUID());
|
||||||
|
if (endTimeState != null) {
|
||||||
|
updateState(CHANNEL_ENDTIME, endTimeState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "nightModeBrightness":
|
||||||
|
int nightModeBrightnessValue = Integer.valueOf(value);
|
||||||
|
currentNightModeBrightness = nightModeBrightnessValue;
|
||||||
|
State nightModeBrightnessState = new PercentType(nightModeBrightnessValue);
|
||||||
|
logger.debug("nightModeBrightnessState '{}' for device '{}' received", nightModeBrightnessState,
|
||||||
|
getThing().getUID());
|
||||||
|
updateState(CHANNEL_NIGHTMODEBRIGHTNESS, nightModeBrightnessState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,9 +420,9 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
if ((subscriptionState.get(subscription) == null) || !subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -409,7 +435,7 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
logger.debug("Removing WeMo GENA subscription for '{}'", this);
|
logger.debug("Removing WeMo GENA subscription for '{}'", this);
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
if ((subscriptionState.get(subscription) != null) && subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
@ -419,9 +445,10 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
if (refreshConfig != null) {
|
if (refreshConfig != null) {
|
||||||
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
||||||
|
@ -455,29 +482,25 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
|
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
|
value = substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
|
||||||
if (value != null) {
|
variable = "BinaryState";
|
||||||
variable = "BinaryState";
|
logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
|
||||||
logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
value = substringBetween(wemoCallResponse, "<brightness>", "</brightness>");
|
||||||
}
|
variable = "brightness";
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<brightness>", "</brightness>");
|
logger.trace("New brightness '{}' for device '{}' received", value, getThing().getUID());
|
||||||
if (value != null) {
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
variable = "brightness";
|
value = substringBetween(wemoCallResponse, "<fader>", "</fader>");
|
||||||
logger.trace("New brightness '{}' for device '{}' received", value, getThing().getUID());
|
variable = "fader";
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
logger.trace("New fader value '{}' for device '{}' received", value, getThing().getUID());
|
||||||
}
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<fader>", "</fader>");
|
|
||||||
if (value != null) {
|
|
||||||
variable = "fader";
|
|
||||||
logger.trace("New fader value '{}' for device '{}' received", value, getThing().getUID());
|
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -494,38 +517,30 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
|
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
logger.trace("GetNightModeConfiguration response '{}' for device '{}' received", wemoCallResponse,
|
logger.trace("GetNightModeConfiguration response '{}' for device '{}' received", wemoCallResponse,
|
||||||
getThing().getUID());
|
getThing().getUID());
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<startTime>", "</startTime>");
|
value = substringBetween(wemoCallResponse, "<startTime>", "</startTime>");
|
||||||
if (value != null) {
|
variable = "startTime";
|
||||||
variable = "startTime";
|
logger.trace("New startTime '{}' for device '{}' received", value, getThing().getUID());
|
||||||
logger.trace("New startTime '{}' for device '{}' received", value, getThing().getUID());
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
value = substringBetween(wemoCallResponse, "<endTime>", "</endTime>");
|
||||||
}
|
variable = "endTime";
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<endTime>", "</endTime>");
|
logger.trace("New endTime '{}' for device '{}' received", value, getThing().getUID());
|
||||||
if (value != null) {
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
variable = "endTime";
|
value = substringBetween(wemoCallResponse, "<nightMode>", "</nightMode>");
|
||||||
logger.trace("New endTime '{}' for device '{}' received", value, getThing().getUID());
|
variable = "nightMode";
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
logger.trace("New nightMode state '{}' for device '{}' received", value, getThing().getUID());
|
||||||
}
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<nightMode>", "</nightMode>");
|
value = substringBetween(wemoCallResponse, "<nightModeBrightness>", "</nightModeBrightness>");
|
||||||
if (value != null) {
|
variable = "nightModeBrightness";
|
||||||
variable = "nightMode";
|
logger.trace("New nightModeBrightness '{}' for device '{}' received", value, getThing().getUID());
|
||||||
logger.trace("New nightMode state '{}' for device '{}' received", value, getThing().getUID());
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
|
||||||
}
|
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<nightModeBrightness>",
|
|
||||||
"</nightModeBrightness>");
|
|
||||||
if (value != null) {
|
|
||||||
variable = "nightModeBrightness";
|
|
||||||
logger.trace("New nightModeBrightness '{}' for device '{}' received", value,
|
|
||||||
getThing().getUID());
|
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -536,37 +551,19 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL(String actionService) {
|
public @Nullable State getDateTimeState(String attributeValue) {
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
long value = 0;
|
||||||
String wemoURL = null;
|
try {
|
||||||
if (descriptorURL != null) {
|
value = Long.parseLong(attributeValue);
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
} catch (NumberFormatException e) {
|
||||||
wemoURL = deviceURL + "/upnp/control/" + actionService + "1";
|
logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||||
return wemoURL;
|
getThing().getUID());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochSecond(value), TimeZone.getDefault().toZoneId());
|
||||||
}
|
State dateTimeState = new DateTimeType(zoned);
|
||||||
|
logger.trace("New attribute brewed '{}' received", dateTimeState);
|
||||||
@SuppressWarnings("null")
|
return dateTimeState;
|
||||||
public State getDateTimeState(String attributeValue) {
|
|
||||||
if (attributeValue != null) {
|
|
||||||
long value = 0;
|
|
||||||
try {
|
|
||||||
value = Long.parseLong(attributeValue) * 1000; // convert s to ms
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
logger.warn("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
|
||||||
getThing().getUID());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(value),
|
|
||||||
TimeZone.getDefault().toZoneId());
|
|
||||||
State dateTimeState = new DateTimeType(zoned);
|
|
||||||
if (dateTimeState != null) {
|
|
||||||
logger.trace("New attribute '{}' received", dateTimeState);
|
|
||||||
return dateTimeState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBinaryState(String action, String argument, String value) {
|
public void setBinaryState(String action, String argument, String value) {
|
||||||
|
@ -576,10 +573,12 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||||
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<" + argument
|
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<" + argument
|
||||||
+ ">" + value + "</" + argument + ">" + "</u:" + action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ ">" + value + "</" + argument + ">" + "</u:" + action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
String wemoURL = getWemoURL("basicevent");
|
|
||||||
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
logger.trace("About to send content to Dimmer {}", content);
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
|
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
|
||||||
|
@ -595,10 +594,12 @@ public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
+ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||||
+ "<s:Body>" + "<u:SetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + value
|
+ "<s:Body>" + "<u:SetBinaryState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + value
|
||||||
+ "</u:SetBinaryState>" + "</s:Body>" + "</s:Envelope>";
|
+ "</u:SetBinaryState>" + "</s:Body>" + "</s:Envelope>";
|
||||||
String wemoURL = getWemoURL("basicevent");
|
|
||||||
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
logger.trace("About to send content to Dimmer {}", content);
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
|
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -30,10 +30,10 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.net.http.HttpUtil;
|
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOService;
|
import org.openhab.core.io.transport.upnp.UpnpIOService;
|
||||||
import org.openhab.core.library.types.DateTimeType;
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
@ -54,13 +54,13 @@ import org.slf4j.LoggerFactory;
|
||||||
* The {@link WemoHandler} is responsible for handling commands, which are
|
* The {@link WemoHandler} is responsible for handling commands, which are
|
||||||
* sent to one of the channels and to update their states.
|
* sent to one of the channels and to update their states.
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution; Added support for WeMo Insight energy measurement
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
* @author Kai Kreuzer - some refactoring for performance and simplification
|
* @author Kai Kreuzer - some refactoring for performance and simplification
|
||||||
* @author Stefan Bußweiler - Added new thing status handling
|
* @author Stefan Bußweiler - Added new thing status handling
|
||||||
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
|
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
|
||||||
* @author Mihir Patil - Added standby switch
|
* @author Mihir Patil - Added standby switch
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoHandler.class);
|
||||||
|
@ -73,16 +73,10 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
|
|
||||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
// protected static final int SUBSCRIPTION_DURATION = WemoBindingConstants.SUBSCRIPTION_DURATION;
|
protected UpnpIOService service;
|
||||||
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
private UpnpIOService service;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
|
||||||
/**
|
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private final int DEFAULT_REFRESH_INTERVAL = 120;
|
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
|
||||||
|
|
||||||
private final Runnable refreshRunnable = new Runnable() {
|
private final Runnable refreshRunnable = new Runnable() {
|
||||||
|
|
||||||
|
@ -102,18 +96,13 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
|
public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpCaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemohttpCaller;
|
this.service = upnpIOService;
|
||||||
|
this.wemoCall = wemoHttpCaller;
|
||||||
|
|
||||||
logger.debug("Creating a WemoHandler for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoHandler for thing '{}'", getThing().getUID());
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -135,12 +124,12 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoHandler disposed.");
|
logger.debug("WeMoHandler disposed.");
|
||||||
|
|
||||||
removeSubscription();
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
job.cancel(true);
|
||||||
refreshJob.cancel(true);
|
|
||||||
refreshJob = null;
|
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -172,10 +161,11 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
|
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
|
||||||
+ "</s:Envelope>";
|
+ "</s:Envelope>";
|
||||||
|
|
||||||
String wemoURL = getWemoURL("basicevent");
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
logger.error("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||||
|
@ -188,20 +178,24 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
|
if (service != null) {
|
||||||
subscriptionState.put(service, succeeded);
|
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
|
||||||
|
succeeded ? "succeeded" : "failed");
|
||||||
|
subscriptionState.put(service, succeeded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("null")
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
||||||
new Object[] { variable, value, service, this.getThing().getUID() });
|
new Object[] { variable, value, service, this.getThing().getUID() });
|
||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
|
||||||
this.stateMap.put(variable, value);
|
if (variable != null && value != null) {
|
||||||
|
this.stateMap.put(variable, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (getThing().getThingTypeUID().getId().equals("insight")) {
|
if (getThing().getThingTypeUID().getId().equals("insight")) {
|
||||||
String insightParams = stateMap.get("InsightParams");
|
String insightParams = stateMap.get("InsightParams");
|
||||||
|
@ -212,11 +206,9 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
if (splitInsightParams[0] != null) {
|
if (splitInsightParams[0] != null) {
|
||||||
OnOffType binaryState = null;
|
OnOffType binaryState = null;
|
||||||
binaryState = splitInsightParams[0].equals("0") ? OnOffType.OFF : OnOffType.ON;
|
binaryState = splitInsightParams[0].equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
if (binaryState != null) {
|
logger.trace("New InsightParam binaryState '{}' for device '{}' received", binaryState,
|
||||||
logger.trace("New InsightParam binaryState '{}' for device '{}' received", binaryState,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_STATE, binaryState);
|
||||||
updateState(CHANNEL_STATE, binaryState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long lastChangedAt = 0;
|
long lastChangedAt = 0;
|
||||||
|
@ -237,77 +229,57 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
|
|
||||||
State lastOnFor = DecimalType.valueOf(splitInsightParams[2]);
|
State lastOnFor = DecimalType.valueOf(splitInsightParams[2]);
|
||||||
if (lastOnFor != null) {
|
logger.trace("New InsightParam lastOnFor '{}' for device '{}' received", lastOnFor,
|
||||||
logger.trace("New InsightParam lastOnFor '{}' for device '{}' received", lastOnFor,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_LASTONFOR, lastOnFor);
|
||||||
updateState(CHANNEL_LASTONFOR, lastOnFor);
|
|
||||||
}
|
|
||||||
|
|
||||||
State onToday = DecimalType.valueOf(splitInsightParams[3]);
|
State onToday = DecimalType.valueOf(splitInsightParams[3]);
|
||||||
if (onToday != null) {
|
logger.trace("New InsightParam onToday '{}' for device '{}' received", onToday, getThing().getUID());
|
||||||
logger.trace("New InsightParam onToday '{}' for device '{}' received", onToday,
|
updateState(CHANNEL_ONTODAY, onToday);
|
||||||
getThing().getUID());
|
|
||||||
updateState(CHANNEL_ONTODAY, onToday);
|
|
||||||
}
|
|
||||||
|
|
||||||
State onTotal = DecimalType.valueOf(splitInsightParams[4]);
|
State onTotal = DecimalType.valueOf(splitInsightParams[4]);
|
||||||
if (onTotal != null) {
|
logger.trace("New InsightParam onTotal '{}' for device '{}' received", onTotal, getThing().getUID());
|
||||||
logger.trace("New InsightParam onTotal '{}' for device '{}' received", onTotal,
|
updateState(CHANNEL_ONTOTAL, onTotal);
|
||||||
getThing().getUID());
|
|
||||||
updateState(CHANNEL_ONTOTAL, onTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
State timespan = DecimalType.valueOf(splitInsightParams[5]);
|
State timespan = DecimalType.valueOf(splitInsightParams[5]);
|
||||||
if (timespan != null) {
|
logger.trace("New InsightParam timespan '{}' for device '{}' received", timespan, getThing().getUID());
|
||||||
logger.trace("New InsightParam timespan '{}' for device '{}' received", timespan,
|
updateState(CHANNEL_TIMESPAN, timespan);
|
||||||
getThing().getUID());
|
|
||||||
updateState(CHANNEL_TIMESPAN, timespan);
|
|
||||||
}
|
|
||||||
|
|
||||||
State averagePower = DecimalType.valueOf(splitInsightParams[6]); // natively given in W
|
State averagePower = DecimalType.valueOf(splitInsightParams[6]); // natively given in W
|
||||||
if (averagePower != null) {
|
logger.trace("New InsightParam averagePower '{}' for device '{}' received", averagePower,
|
||||||
logger.trace("New InsightParam averagePower '{}' for device '{}' received", averagePower,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_AVERAGEPOWER, averagePower);
|
||||||
updateState(CHANNEL_AVERAGEPOWER, averagePower);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal currentMW = new BigDecimal(splitInsightParams[7]);
|
BigDecimal currentMW = new BigDecimal(splitInsightParams[7]);
|
||||||
State currentPower = new DecimalType(currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
|
State currentPower = new DecimalType(currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
|
||||||
// mW to W
|
// mW to W
|
||||||
if (currentPower != null) {
|
logger.trace("New InsightParam currentPower '{}' for device '{}' received", currentPower,
|
||||||
logger.trace("New InsightParam currentPower '{}' for device '{}' received", currentPower,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_CURRENTPOWER, currentPower);
|
||||||
updateState(CHANNEL_CURRENTPOWER, currentPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal energyTodayMWMin = new BigDecimal(splitInsightParams[8]);
|
BigDecimal energyTodayMWMin = new BigDecimal(splitInsightParams[8]);
|
||||||
// recalculate mW-mins to Wh
|
// recalculate mW-mins to Wh
|
||||||
State energyToday = new DecimalType(
|
State energyToday = new DecimalType(
|
||||||
energyTodayMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
|
energyTodayMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
|
||||||
if (energyToday != null) {
|
logger.trace("New InsightParam energyToday '{}' for device '{}' received", energyToday,
|
||||||
logger.trace("New InsightParam energyToday '{}' for device '{}' received", energyToday,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_ENERGYTODAY, energyToday);
|
||||||
updateState(CHANNEL_ENERGYTODAY, energyToday);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal energyTotalMWMin = new BigDecimal(splitInsightParams[9]);
|
BigDecimal energyTotalMWMin = new BigDecimal(splitInsightParams[9]);
|
||||||
// recalculate mW-mins to Wh
|
// recalculate mW-mins to Wh
|
||||||
State energyTotal = new DecimalType(
|
State energyTotal = new DecimalType(
|
||||||
energyTotalMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
|
energyTotalMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
|
||||||
if (energyTotal != null) {
|
logger.trace("New InsightParam energyTotal '{}' for device '{}' received", energyTotal,
|
||||||
logger.trace("New InsightParam energyTotal '{}' for device '{}' received", energyTotal,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_ENERGYTOTAL, energyTotal);
|
||||||
updateState(CHANNEL_ENERGYTOTAL, energyTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal standByLimitMW = new BigDecimal(splitInsightParams[10]);
|
BigDecimal standByLimitMW = new BigDecimal(splitInsightParams[10]);
|
||||||
State standByLimit = new DecimalType(standByLimitMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
|
State standByLimit = new DecimalType(standByLimitMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
|
||||||
// mW to W
|
// mW to W
|
||||||
if (standByLimit != null) {
|
logger.trace("New InsightParam standByLimit '{}' for device '{}' received", standByLimit,
|
||||||
logger.trace("New InsightParam standByLimit '{}' for device '{}' received", standByLimit,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_STANDBYLIMIT, standByLimit);
|
||||||
updateState(CHANNEL_STANDBYLIMIT, standByLimit);
|
|
||||||
}
|
|
||||||
if (currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue() > standByLimitMW
|
if (currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue() > standByLimitMW
|
||||||
.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue()) {
|
.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue()) {
|
||||||
updateState(CHANNEL_ONSTANDBY, OnOffType.OFF);
|
updateState(CHANNEL_ONSTANDBY, OnOffType.OFF);
|
||||||
|
@ -316,11 +288,10 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
State state = stateMap.get("BinaryState").equals("0") ? OnOffType.OFF : OnOffType.ON;
|
String binaryState = stateMap.get("BinaryState");
|
||||||
|
if (binaryState != null) {
|
||||||
logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
|
State state = binaryState.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
|
logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
|
||||||
if (state != null) {
|
|
||||||
if (getThing().getThingTypeUID().getId().equals("motion")) {
|
if (getThing().getThingTypeUID().getId().equals("motion")) {
|
||||||
updateState(CHANNEL_MOTIONDETECTION, state);
|
updateState(CHANNEL_MOTIONDETECTION, state);
|
||||||
if (state.equals(OnOffType.ON)) {
|
if (state.equals(OnOffType.ON)) {
|
||||||
|
@ -341,19 +312,18 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) == null) || !subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
|
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
|
||||||
subscription = "insight1";
|
subscription = "insight1";
|
||||||
if ((subscriptionState.get(subscription) == null)
|
if (subscriptionState.get(subscription) == null) {
|
||||||
|| !subscriptionState.get(subscription).booleanValue()) {
|
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||||
subscription);
|
subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,15 +340,14 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) != null) && subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
|
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
|
||||||
subscription = "insight1";
|
subscription = "insight1";
|
||||||
if ((subscriptionState.get(subscription) != null)
|
if (subscriptionState.get(subscription) != null) {
|
||||||
&& subscriptionState.get(subscription).booleanValue()) {
|
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
@ -389,9 +358,10 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
if (refreshConfig != null) {
|
if (refreshConfig != null) {
|
||||||
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
||||||
|
@ -433,20 +403,20 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, actionService);
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
||||||
if (variable.equals("InsightParams")) {
|
if (variable.equals("InsightParams")) {
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<InsightParams>", "</InsightParams>");
|
value = substringBetween(wemoCallResponse, "<InsightParams>", "</InsightParams>");
|
||||||
} else {
|
} else {
|
||||||
value = StringUtils.substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
|
value = substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
|
||||||
}
|
|
||||||
if (value != null) {
|
|
||||||
logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
|
|
||||||
this.onValueReceived(variable, value, actionService + "1");
|
|
||||||
}
|
}
|
||||||
|
logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
|
||||||
|
this.onValueReceived(variable, value, actionService + "1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -454,43 +424,6 @@ public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL(String actionService) {
|
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
int portCheckStart = 49151;
|
|
||||||
int portCheckStop = 49157;
|
|
||||||
String wemoURL = null;
|
|
||||||
String host = null;
|
|
||||||
String port = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
host = StringUtils.substringBetween(descriptorURL.toString(), "://", ":");
|
|
||||||
for (int i = portCheckStart; i < portCheckStop; i++) {
|
|
||||||
try {
|
|
||||||
boolean portFound = servicePing(host, i);
|
|
||||||
if (portFound) {
|
|
||||||
logger.trace("WeMo device {} responded at Port {}", getUDN(), i);
|
|
||||||
port = String.valueOf(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wemoURL = "http://" + host + ":" + port + "/upnp/control/" + actionService + "1";
|
|
||||||
logger.trace("WeMo url {}", wemoURL);
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean servicePing(String host, int port) {
|
|
||||||
logger.trace("Ping WeMo device at '{}:{}'", host, port);
|
|
||||||
try {
|
|
||||||
HttpUtil.executeUrl("GET", "http://" + host + ":" + port, 250);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChanged(boolean status) {
|
public void onStatusChanged(boolean status) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
@ -29,8 +30,8 @@ import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -62,25 +63,22 @@ import org.xml.sax.SAXException;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution;
|
* @author Hans-Jörg Merk - Initial contribution;
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoHolmesHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoHolmesHandler.class);
|
||||||
|
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_PURIFIER);
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_PURIFIER);
|
||||||
|
|
||||||
/**
|
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private static final int DEFAULT_REFRESH_INTERVAL_SECONDS = 120;
|
|
||||||
private static final int FILTER_LIFE_DAYS = 330;
|
private static final int FILTER_LIFE_DAYS = 330;
|
||||||
private static final int FILTER_LIFE_MINS = FILTER_LIFE_DAYS * 24 * 60;
|
private static final int FILTER_LIFE_MINS = FILTER_LIFE_DAYS * 24 * 60;
|
||||||
private final Map<String, Boolean> subscriptionState = new HashMap<>();
|
private final Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
|
||||||
private final Runnable refreshRunnable = () -> {
|
private final Runnable refreshRunnable = () -> {
|
||||||
if (!isUpnpDeviceRegistered()) {
|
if (!isUpnpDeviceRegistered()) {
|
||||||
|
@ -91,18 +89,13 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
|
public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpCaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemohttpCaller;
|
this.service = upnpIOService;
|
||||||
|
this.wemoCall = wemoHttpCaller;
|
||||||
|
|
||||||
logger.debug("Creating a WemoHolmesHandler for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoHolmesHandler for thing '{}'", getThing().getUID());
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,12 +117,12 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WemoHolmesHandler disposed.");
|
logger.debug("WemoHolmesHandler disposed.");
|
||||||
|
|
||||||
removeSubscription();
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
job.cancel(true);
|
||||||
refreshJob.cancel(true);
|
|
||||||
refreshJob = null;
|
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -243,10 +236,12 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ "<attributeList><attribute><name>" + attribute + "</name><value>" + value
|
+ "<attributeList><attribute><name>" + attribute + "</name><value>" + value
|
||||||
+ "</value></attribute></attributeList>" + "</u:SetAttributes>" + "</s:Body>"
|
+ "</value></attribute></attributeList>" + "</u:SetAttributes>" + "</s:Body>"
|
||||||
+ "</s:Envelope>";
|
+ "</s:Envelope>";
|
||||||
String wemoURL = getWemoURL("deviceevent");
|
|
||||||
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "deviceevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
||||||
|
@ -256,18 +251,23 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
|
if (service != null) {
|
||||||
subscriptionState.put(service, succeeded);
|
logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
|
||||||
|
succeeded ? "succeeded" : "failed");
|
||||||
|
subscriptionState.put(service, succeeded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'", variable, value, service,
|
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'", variable, value, service,
|
||||||
this.getThing().getUID());
|
this.getThing().getUID());
|
||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
this.stateMap.put(variable, value);
|
if (variable != null && value != null) {
|
||||||
|
this.stateMap.put(variable, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onSubscription() {
|
private synchronized void onSubscription() {
|
||||||
|
@ -276,9 +276,9 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
|
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) == null) || !subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), subscription);
|
||||||
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(subscription, true);
|
subscriptionState.put(subscription, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
String subscription = "basicevent1";
|
String subscription = "basicevent1";
|
||||||
|
|
||||||
if ((subscriptionState.get(subscription) != null) && subscriptionState.get(subscription).booleanValue()) {
|
if (subscriptionState.get(subscription) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||||
service.removeSubscription(this, subscription);
|
service.removeSubscription(this, subscription);
|
||||||
}
|
}
|
||||||
|
@ -305,11 +305,12 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL_SECONDS;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVAL_SECONDS
|
refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVALL_SECONDS
|
||||||
: ((BigDecimal) refreshConfig).intValue();
|
: ((BigDecimal) refreshConfig).intValue();
|
||||||
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
@ -340,18 +341,19 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, actionService);
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
|
||||||
|
|
||||||
String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
|
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||||
"</attributeList>");
|
|
||||||
|
|
||||||
// Due to Belkins bad response formatting, we need to run this twice.
|
// Due to Belkins bad response formatting, we need to run this twice.
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
|
|
||||||
logger.trace("AirPurifier response '{}' for device '{}' received", stringParser,
|
logger.trace("AirPurifier response '{}' for device '{}' received", stringParser,
|
||||||
getThing().getUID());
|
getThing().getUID());
|
||||||
|
@ -557,17 +559,6 @@ public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOPart
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL(String actionService) {
|
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
String wemoURL = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
|
||||||
wemoURL = deviceURL + "/upnp/control/" + actionService + "1";
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCharacterDataFromElement(Element e) {
|
public static String getCharacterDataFromElement(Element e) {
|
||||||
Node child = e.getFirstChild();
|
Node child = e.getFirstChild();
|
||||||
if (child instanceof CharacterData) {
|
if (child instanceof CharacterData) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -21,8 +22,8 @@ import java.util.Map;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -49,6 +50,7 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoLightHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoLightHandler.class);
|
||||||
|
@ -56,10 +58,11 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||||
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
private WemoBridgeHandler wemoBridgeHandler;
|
private @Nullable WemoBridgeHandler wemoBridgeHandler;
|
||||||
|
|
||||||
private String wemoLightID;
|
private @Nullable String wemoLightID;
|
||||||
|
|
||||||
private int currentBrightness;
|
private int currentBrightness;
|
||||||
|
|
||||||
|
@ -70,19 +73,12 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
|
|
||||||
protected static final String SUBSCRIPTION = "bridge1";
|
protected static final String SUBSCRIPTION = "bridge1";
|
||||||
|
|
||||||
protected static final int SUBSCRIPTION_DURATION = 600;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private final int DEFAULT_REFRESH_INTERVAL = 60;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default refresh initial delay in Seconds.
|
* The default refresh initial delay in Seconds.
|
||||||
*/
|
*/
|
||||||
private static final int DEFAULT_REFRESH_INITIAL_DELAY = 15;
|
private static final int DEFAULT_REFRESH_INITIAL_DELAY = 15;
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
|
|
||||||
private final Runnable refreshRunnable = new Runnable() {
|
private final Runnable refreshRunnable = new Runnable() {
|
||||||
|
|
||||||
|
@ -103,16 +99,10 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoLightHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
|
public WemoLightHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpcaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemoHttpcaller;
|
this.service = upnpIOService;
|
||||||
|
this.wemoCall = wemoHttpcaller;
|
||||||
if (upnpIOService != null) {
|
|
||||||
logger.debug("UPnPIOService '{}'", upnpIOService);
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,17 +110,13 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
// initialize() is only called if the required parameter 'deviceID' is available
|
// initialize() is only called if the required parameter 'deviceID' is available
|
||||||
wemoLightID = (String) getConfig().get(DEVICE_ID);
|
wemoLightID = (String) getConfig().get(DEVICE_ID);
|
||||||
|
|
||||||
if (getBridge() != null) {
|
final Bridge bridge = getBridge();
|
||||||
logger.debug("Initializing WemoLightHandler for LightID '{}'", wemoLightID);
|
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||||
if (getBridge().getStatus() == ThingStatus.ONLINE) {
|
updateStatus(ThingStatus.ONLINE);
|
||||||
updateStatus(ThingStatus.ONLINE);
|
onSubscription();
|
||||||
onSubscription();
|
onUpdate();
|
||||||
onUpdate();
|
|
||||||
} else {
|
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
updateStatus(ThingStatus.OFFLINE);
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,10 +128,11 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
onUpdate();
|
onUpdate();
|
||||||
} else {
|
} else {
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
refreshJob.cancel(true);
|
if (job != null && !job.isCancelled()) {
|
||||||
refreshJob = null;
|
job.cancel(true);
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,28 +140,26 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoLightHandler disposed.");
|
logger.debug("WeMoLightHandler disposed.");
|
||||||
|
|
||||||
removeSubscription();
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
job.cancel(true);
|
||||||
refreshJob.cancel(true);
|
|
||||||
refreshJob = null;
|
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
|
removeSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized WemoBridgeHandler getWemoBridgeHandler() {
|
private synchronized @Nullable WemoBridgeHandler getWemoBridgeHandler() {
|
||||||
if (this.wemoBridgeHandler == null) {
|
Bridge bridge = getBridge();
|
||||||
Bridge bridge = getBridge();
|
if (bridge == null) {
|
||||||
if (bridge == null) {
|
logger.error("Required bridge not defined for device {}.", wemoLightID);
|
||||||
logger.error("Required bridge not defined for device {}.", wemoLightID);
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
ThingHandler handler = bridge.getHandler();
|
||||||
ThingHandler handler = bridge.getHandler();
|
if (handler instanceof WemoBridgeHandler) {
|
||||||
if (handler instanceof WemoBridgeHandler) {
|
this.wemoBridgeHandler = (WemoBridgeHandler) handler;
|
||||||
this.wemoBridgeHandler = (WemoBridgeHandler) handler;
|
} else {
|
||||||
} else {
|
logger.debug("No available bridge handler found for {} bridge {} .", wemoLightID, bridge.getUID());
|
||||||
logger.debug("No available bridge handler found for {} bridge {} .", wemoLightID, bridge.getUID());
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return this.wemoBridgeHandler;
|
return this.wemoBridgeHandler;
|
||||||
}
|
}
|
||||||
|
@ -266,10 +251,11 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
+ "</CapabilityValue></DeviceStatus>" + "</DeviceStatusList>"
|
+ "</CapabilityValue></DeviceStatus>" + "</DeviceStatusList>"
|
||||||
+ "</u:SetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
+ "</u:SetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
String wemoURL = getWemoURL();
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "bridge");
|
||||||
|
|
||||||
if (wemoURL != null && capability != null && value != null) {
|
if (wemoURL != null && capability != null && value != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
if (capability.equals("10008")) {
|
if (capability.equals("10008")) {
|
||||||
OnOffType binaryState = null;
|
OnOffType binaryState = null;
|
||||||
|
@ -285,7 +271,7 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUDN() {
|
public @Nullable String getUDN() {
|
||||||
WemoBridgeHandler wemoBridge = getWemoBridgeHandler();
|
WemoBridgeHandler wemoBridge = getWemoBridgeHandler();
|
||||||
if (wemoBridge == null) {
|
if (wemoBridge == null) {
|
||||||
logger.debug("wemoBridgeHandler not found");
|
logger.debug("wemoBridgeHandler not found");
|
||||||
|
@ -307,14 +293,14 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
+ "<s:Body>" + "<u:GetDeviceStatus xmlns:u=\"urn:Belkin:service:bridge:1\">" + "<DeviceIDs>"
|
+ "<s:Body>" + "<u:GetDeviceStatus xmlns:u=\"urn:Belkin:service:bridge:1\">" + "<DeviceIDs>"
|
||||||
+ wemoLightID + "</DeviceIDs>" + "</u:GetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
+ wemoLightID + "</DeviceIDs>" + "</u:GetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
String wemoURL = getWemoURL();
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "bridge");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
wemoCallResponse = StringEscapeUtils.unescapeXml(wemoCallResponse);
|
wemoCallResponse = unescapeXml(wemoCallResponse);
|
||||||
String response = StringUtils.substringBetween(wemoCallResponse, "<CapabilityValue>",
|
String response = substringBetween(wemoCallResponse, "<CapabilityValue>", "</CapabilityValue>");
|
||||||
"</CapabilityValue>");
|
|
||||||
logger.trace("wemoNewLightState = {}", response);
|
logger.trace("wemoNewLightState = {}", response);
|
||||||
String[] splitResponse = response.split(",");
|
String[] splitResponse = response.split(",");
|
||||||
if (splitResponse[0] != null) {
|
if (splitResponse[0] != null) {
|
||||||
|
@ -341,15 +327,15 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
logger.trace("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
logger.trace("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
||||||
new Object[] { variable, value, service, this.getThing().getUID() });
|
new Object[] { variable, value, service, this.getThing().getUID() });
|
||||||
String capabilityId = StringUtils.substringBetween(value, "<CapabilityId>", "</CapabilityId>");
|
String capabilityId = substringBetween(value, "<CapabilityId>", "</CapabilityId>");
|
||||||
String newValue = StringUtils.substringBetween(value, "<Value>", "</Value>");
|
String newValue = substringBetween(value, "<Value>", "</Value>");
|
||||||
switch (capabilityId) {
|
switch (capabilityId) {
|
||||||
case "10006":
|
case "10006":
|
||||||
OnOffType binaryState = null;
|
OnOffType binaryState = null;
|
||||||
|
@ -377,9 +363,9 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
logger.debug("Checking WeMo GENA subscription for '{}'", this);
|
||||||
|
|
||||||
if ((subscriptionState.get(SUBSCRIPTION) == null) || !subscriptionState.get(SUBSCRIPTION).booleanValue()) {
|
if (subscriptionState.get(SUBSCRIPTION) == null) {
|
||||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), SUBSCRIPTION);
|
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(), SUBSCRIPTION);
|
||||||
service.addSubscription(this, SUBSCRIPTION, SUBSCRIPTION_DURATION);
|
service.addSubscription(this, SUBSCRIPTION, SUBSCRIPTION_DURATION_SECONDS);
|
||||||
subscriptionState.put(SUBSCRIPTION, true);
|
subscriptionState.put(SUBSCRIPTION, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -392,7 +378,7 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
if (service.isRegistered(this)) {
|
if (service.isRegistered(this)) {
|
||||||
logger.debug("Removing WeMo GENA subscription for '{}'", this);
|
logger.debug("Removing WeMo GENA subscription for '{}'", this);
|
||||||
|
|
||||||
if ((subscriptionState.get(SUBSCRIPTION) != null) && subscriptionState.get(SUBSCRIPTION).booleanValue()) {
|
if (subscriptionState.get(SUBSCRIPTION) != null) {
|
||||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), SUBSCRIPTION);
|
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), SUBSCRIPTION);
|
||||||
service.removeSubscription(this, SUBSCRIPTION);
|
service.removeSubscription(this, SUBSCRIPTION);
|
||||||
}
|
}
|
||||||
|
@ -403,9 +389,10 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
if (refreshConfig != null) {
|
if (refreshConfig != null) {
|
||||||
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
||||||
|
@ -419,15 +406,4 @@ public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
private boolean isUpnpDeviceRegistered() {
|
private boolean isUpnpDeviceRegistered() {
|
||||||
return service.isRegistered(this);
|
return service.isRegistered(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL() {
|
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
String wemoURL = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
|
||||||
wemoURL = deviceURL + "/upnp/control/bridge1";
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.binding.wemo.internal.handler;
|
package org.openhab.binding.wemo.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
|
||||||
|
import static org.openhab.binding.wemo.internal.WemoUtil.*;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
@ -25,8 +26,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
|
||||||
|
@ -55,7 +56,7 @@ import org.xml.sax.InputSource;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoMakerHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoMakerHandler.class);
|
||||||
|
@ -63,13 +64,9 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_MAKER);
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_MAKER);
|
||||||
|
|
||||||
private UpnpIOService service;
|
private UpnpIOService service;
|
||||||
|
private WemoHttpCall wemoCall;
|
||||||
|
|
||||||
/**
|
private @Nullable ScheduledFuture<?> refreshJob;
|
||||||
* The default refresh interval in Seconds.
|
|
||||||
*/
|
|
||||||
private final int DEFAULT_REFRESH_INTERVAL = 15;
|
|
||||||
|
|
||||||
private ScheduledFuture<?> refreshJob;
|
|
||||||
|
|
||||||
private final Runnable refreshRunnable = new Runnable() {
|
private final Runnable refreshRunnable = new Runnable() {
|
||||||
|
|
||||||
|
@ -85,17 +82,12 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
};
|
};
|
||||||
|
|
||||||
public WemoMakerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
|
public WemoMakerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
|
||||||
super(thing);
|
super(thing, wemoHttpcaller);
|
||||||
|
|
||||||
this.wemoHttpCaller = wemoHttpcaller;
|
this.service = upnpIOService;
|
||||||
|
this.wemoCall = wemoHttpcaller;
|
||||||
|
|
||||||
logger.debug("Creating a WemoMakerHandler for thing '{}'", getThing().getUID());
|
logger.debug("Creating a WemoMakerHandler for thing '{}'", getThing().getUID());
|
||||||
|
|
||||||
if (upnpIOService != null) {
|
|
||||||
this.service = upnpIOService;
|
|
||||||
} else {
|
|
||||||
logger.debug("upnpIOService not set.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,10 +107,11 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
logger.debug("WeMoMakerHandler disposed.");
|
logger.debug("WeMoMakerHandler disposed.");
|
||||||
|
|
||||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
refreshJob.cancel(true);
|
if (job != null && !job.isCancelled()) {
|
||||||
refreshJob = null;
|
job.cancel(true);
|
||||||
}
|
}
|
||||||
|
refreshJob = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,11 +143,11 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
|
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
|
||||||
+ "</s:Envelope>";
|
+ "</s:Envelope>";
|
||||||
|
|
||||||
String wemoURL = getWemoURL("basicevent");
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, "basicevent");
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
@SuppressWarnings("unused")
|
wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Failed to send command '{}' for device '{}' ", command, getThing().getUID(), e);
|
logger.error("Failed to send command '{}' for device '{}' ", command, getThing().getUID(), e);
|
||||||
|
@ -172,16 +165,15 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void onUpdate() {
|
private synchronized void onUpdate() {
|
||||||
if (service.isRegistered(this)) {
|
ScheduledFuture<?> job = refreshJob;
|
||||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
if (job == null || job.isCancelled()) {
|
||||||
Configuration config = getThing().getConfiguration();
|
Configuration config = getThing().getConfiguration();
|
||||||
int refreshInterval = DEFAULT_REFRESH_INTERVAL;
|
int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
|
||||||
Object refreshConfig = config.get("refresh");
|
Object refreshConfig = config.get("refresh");
|
||||||
if (refreshConfig != null) {
|
if (refreshConfig != null) {
|
||||||
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
refreshInterval = ((BigDecimal) refreshConfig).intValue();
|
||||||
}
|
|
||||||
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +185,6 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
/**
|
/**
|
||||||
* The {@link updateWemoState} polls the actual state of a WeMo Maker.
|
* The {@link updateWemoState} polls the actual state of a WeMo Maker.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("null")
|
|
||||||
protected void updateWemoState() {
|
protected void updateWemoState() {
|
||||||
String action = "GetAttributes";
|
String action = "GetAttributes";
|
||||||
String actionService = "deviceevent";
|
String actionService = "deviceevent";
|
||||||
|
@ -205,18 +196,20 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
+ action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String wemoURL = getWemoURL(actionService);
|
URL descriptorURL = service.getDescriptorURL(this);
|
||||||
|
String wemoURL = getWemoURL(descriptorURL, actionService);
|
||||||
|
|
||||||
if (wemoURL != null) {
|
if (wemoURL != null) {
|
||||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
|
||||||
if (wemoCallResponse != null) {
|
if (wemoCallResponse != null) {
|
||||||
try {
|
try {
|
||||||
String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
|
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||||
"</attributeList>");
|
logger.trace("Escaped Maker response for device '{}' :", getThing().getUID());
|
||||||
|
logger.trace("'{}'", stringParser);
|
||||||
|
|
||||||
// Due to Belkins bad response formatting, we need to run this twice.
|
// Due to Belkins bad response formatting, we need to run this twice.
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
stringParser = StringEscapeUtils.unescapeXml(stringParser);
|
stringParser = unescapeXml(stringParser);
|
||||||
|
|
||||||
logger.trace("Maker response '{}' for device '{}' received", stringParser, getThing().getUID());
|
logger.trace("Maker response '{}' for device '{}' received", stringParser, getThing().getUID());
|
||||||
|
|
||||||
stringParser = "<data>" + stringParser + "</data>";
|
stringParser = "<data>" + stringParser + "</data>";
|
||||||
|
@ -253,19 +246,15 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
switch (attributeName) {
|
switch (attributeName) {
|
||||||
case "Switch":
|
case "Switch":
|
||||||
State relayState = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
State relayState = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
|
||||||
if (relayState != null) {
|
logger.debug("New relayState '{}' for device '{}' received", relayState,
|
||||||
logger.debug("New relayState '{}' for device '{}' received", relayState,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_RELAY, relayState);
|
||||||
updateState(CHANNEL_RELAY, relayState);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "Sensor":
|
case "Sensor":
|
||||||
State sensorState = attributeValue.equals("1") ? OnOffType.OFF : OnOffType.ON;
|
State sensorState = attributeValue.equals("1") ? OnOffType.OFF : OnOffType.ON;
|
||||||
if (sensorState != null) {
|
logger.debug("New sensorState '{}' for device '{}' received", sensorState,
|
||||||
logger.debug("New sensorState '{}' for device '{}' received", sensorState,
|
getThing().getUID());
|
||||||
getThing().getUID());
|
updateState(CHANNEL_SENSOR, sensorState);
|
||||||
updateState(CHANNEL_SENSOR, sensorState);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,17 +268,6 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWemoURL(String actionService) {
|
|
||||||
URL descriptorURL = service.getDescriptorURL(this);
|
|
||||||
String wemoURL = null;
|
|
||||||
if (descriptorURL != null) {
|
|
||||||
String deviceURL = StringUtils.substringBefore(descriptorURL.toString(), "/setup.xml");
|
|
||||||
wemoURL = deviceURL + "/upnp/control/" + actionService + "1";
|
|
||||||
return wemoURL;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getCharacterDataFromElement(Element e) {
|
public static String getCharacterDataFromElement(Element e) {
|
||||||
Node child = e.getFirstChild();
|
Node child = e.getFirstChild();
|
||||||
if (child instanceof CharacterData) {
|
if (child instanceof CharacterData) {
|
||||||
|
@ -304,10 +282,10 @@ public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceSubscribed(String service, boolean succeeded) {
|
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValueReceived(String variable, String value, String service) {
|
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.core.io.net.http.HttpUtil;
|
import org.openhab.core.io.net.http.HttpUtil;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -28,12 +30,12 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Hans-Jörg Merk - Initial contribution
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
public class WemoHttpCall {
|
public class WemoHttpCall {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WemoHttpCall.class);
|
private final Logger logger = LoggerFactory.getLogger(WemoHttpCall.class);
|
||||||
|
|
||||||
public String executeCall(String wemoURL, String soapHeader, String content) {
|
public @Nullable String executeCall(String wemoURL, String soapHeader, String content) {
|
||||||
try {
|
try {
|
||||||
Properties wemoHeaders = new Properties();
|
Properties wemoHeaders = new Properties();
|
||||||
wemoHeaders.setProperty("CONTENT-TYPE", WemoBindingConstants.HTTP_CALL_CONTENT_HEADER);
|
wemoHeaders.setProperty("CONTENT-TYPE", WemoBindingConstants.HTTP_CALL_CONTENT_HEADER);
|
||||||
|
|
|
@ -48,8 +48,8 @@ import org.openhab.core.thing.ThingUID;
|
||||||
public class WemoDiscoveryParticipantTest {
|
public class WemoDiscoveryParticipantTest {
|
||||||
UpnpDiscoveryParticipant participant = new WemoDiscoveryParticipant();
|
UpnpDiscoveryParticipant participant = new WemoDiscoveryParticipant();
|
||||||
|
|
||||||
private final String DEVICE_UDN = GenericWemoOSGiTest.DEVICE_MANUFACTURER + "_3434xxx";
|
private static final String DEVICE_UDN = GenericWemoOSGiTest.DEVICE_MANUFACTURER + "_3434xxx";
|
||||||
private final String DEVICE_FRIENDLY_NAME = "Wemo Test";
|
private static final String DEVICE_FRIENDLY_NAME = "Wemo Test";
|
||||||
|
|
||||||
RemoteDevice createUpnpDevice(String modelName)
|
RemoteDevice createUpnpDevice(String modelName)
|
||||||
throws MalformedURLException, ValidationException, URISyntaxException {
|
throws MalformedURLException, ValidationException, URISyntaxException {
|
||||||
|
|
|
@ -28,10 +28,8 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.jupnp.model.ValidationException;
|
import org.jupnp.model.ValidationException;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoHandler;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
|
||||||
import org.openhab.binding.wemo.internal.test.GenericWemoOSGiTest;
|
import org.openhab.binding.wemo.internal.test.GenericWemoOSGiTest;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
@ -50,14 +48,14 @@ import org.openhab.core.types.RefreshType;
|
||||||
public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
|
|
||||||
// Thing information
|
// Thing information
|
||||||
private final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
|
private static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
|
||||||
private final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
private static final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
||||||
private final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_SOCKET;
|
private static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_SOCKET;
|
||||||
|
|
||||||
// UPnP information
|
// UPnP information
|
||||||
private final String MODEL_NAME = WemoBindingConstants.THING_TYPE_SOCKET.getId();
|
private static final String MODEL_NAME = WemoBindingConstants.THING_TYPE_SOCKET.getId();
|
||||||
private final String SERVICE_ID = "basicevent";
|
private static final String SERVICE_ID = "basicevent";
|
||||||
private final String SERVICE_NUMBER = "1";
|
private static final String SERVICE_NUMBER = "1";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() throws IOException {
|
public void setUp() throws IOException {
|
||||||
|
@ -74,8 +72,7 @@ public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||||
Command command = OnOffType.OFF;
|
Command command = OnOffType.OFF;
|
||||||
|
|
||||||
WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
|
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
||||||
|
@ -111,8 +108,7 @@ public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||||
Command command = RefreshType.REFRESH;
|
Command command = RefreshType.REFRESH;
|
||||||
|
|
||||||
WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
|
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
||||||
|
|
|
@ -40,23 +40,23 @@ import org.openhab.core.types.State;
|
||||||
*/
|
*/
|
||||||
public class WemoHandlerTest {
|
public class WemoHandlerTest {
|
||||||
|
|
||||||
private final ThingTypeUID THING_TYPE = WemoBindingConstants.THING_TYPE_INSIGHT;
|
private static final ThingTypeUID THING_TYPE = WemoBindingConstants.THING_TYPE_INSIGHT;
|
||||||
private final String THING_ID = "test";
|
private static final String THING_ID = "test";
|
||||||
|
|
||||||
private MockWemoHandler handler;
|
private MockWemoHandler handler;
|
||||||
|
|
||||||
private final String SERVICE_ID = "insight";
|
private static final String SERVICE_ID = "insight";
|
||||||
private final String PARAMS_NAME = "InsightParams";
|
private static final String PARAMS_NAME = "InsightParams";
|
||||||
private WemoInsightParams insightParams;
|
private WemoInsightParams insightParams;
|
||||||
|
|
||||||
/** Used for all tests, where expected value is time in seconds **/
|
/** Used for all tests, where expected value is time in seconds **/
|
||||||
private final int TIME_PARAM = 4702;
|
private static final int TIME_PARAM = 4702;
|
||||||
|
|
||||||
/** Represents a state parameter, where 1 stays for ON and 0 stays for OFF **/
|
/** Represents a state parameter, where 1 stays for ON and 0 stays for OFF **/
|
||||||
private final int STATE_PARAM = 1;
|
private static final int STATE_PARAM = 1;
|
||||||
|
|
||||||
/** Represents power in Wats **/
|
/** Represents power in Wats **/
|
||||||
private final int POWER_PARAM = 54;
|
private static final int POWER_PARAM = 54;
|
||||||
|
|
||||||
private final Thing thing = mock(Thing.class);
|
private final Thing thing = mock(Thing.class);
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,8 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.jupnp.model.ValidationException;
|
import org.jupnp.model.ValidationException;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoLightHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoLightHandler;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
|
||||||
import org.openhab.binding.wemo.internal.test.GenericWemoLightOSGiTestParent;
|
import org.openhab.binding.wemo.internal.test.GenericWemoLightOSGiTestParent;
|
||||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
@ -154,8 +152,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
||||||
String capitability) throws MalformedURLException, URISyntaxException, ValidationException {
|
String capitability) throws MalformedURLException, URISyntaxException, ValidationException {
|
||||||
Thing bridge = createBridge(BRIDGE_TYPE_UID);
|
Thing bridge = createBridge(BRIDGE_TYPE_UID);
|
||||||
|
|
||||||
WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
|
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(bridge.getStatus(), is(ThingStatus.ONLINE));
|
assertThat(bridge.getStatus(), is(ThingStatus.ONLINE));
|
||||||
|
|
|
@ -28,10 +28,8 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.jupnp.model.ValidationException;
|
import org.jupnp.model.ValidationException;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.binding.wemo.internal.handler.WemoMakerHandler;
|
import org.openhab.binding.wemo.internal.handler.WemoMakerHandler;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
|
||||||
import org.openhab.binding.wemo.internal.test.GenericWemoOSGiTest;
|
import org.openhab.binding.wemo.internal.test.GenericWemoOSGiTest;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.thing.ChannelUID;
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
@ -51,14 +49,14 @@ import org.openhab.core.types.RefreshType;
|
||||||
public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
|
|
||||||
// Specific Thing information
|
// Specific Thing information
|
||||||
private final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_RELAY;
|
private static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_RELAY;
|
||||||
private final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
private static final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
||||||
private final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MAKER;
|
private static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MAKER;
|
||||||
|
|
||||||
// Specific UpnP service information
|
// Specific UpnP service information
|
||||||
private final String MODEL = THING_TYPE_UID.getId();
|
private static final String MODEL = THING_TYPE_UID.getId();
|
||||||
private final String BASIC_EVENT_SERVICE_ID = "basicevent";
|
private static final String BASIC_EVENT_SERVICE_ID = "basicevent";
|
||||||
private final String SERVICE_NUMBER = "1";
|
private static final String SERVICE_NUMBER = "1";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() throws IOException {
|
public void setUp() throws IOException {
|
||||||
|
@ -75,8 +73,7 @@ public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||||
Command command = OnOffType.OFF;
|
Command command = OnOffType.OFF;
|
||||||
|
|
||||||
WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
|
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
||||||
|
@ -111,8 +108,7 @@ public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
||||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||||
Command command = RefreshType.REFRESH;
|
Command command = RefreshType.REFRESH;
|
||||||
|
|
||||||
WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
|
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
|
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
||||||
|
|
|
@ -17,7 +17,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.binding.wemo.internal.handler.AbstractWemoHandler;
|
import org.openhab.binding.wemo.internal.handler.AbstractWemoHandler;
|
||||||
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
|
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
import org.openhab.core.thing.Channel;
|
import org.openhab.core.thing.Channel;
|
||||||
|
@ -42,19 +41,19 @@ import org.openhab.core.thing.type.ChannelKind;
|
||||||
public class GenericWemoLightOSGiTestParent extends GenericWemoOSGiTest {
|
public class GenericWemoLightOSGiTestParent extends GenericWemoOSGiTest {
|
||||||
|
|
||||||
// Thing information
|
// Thing information
|
||||||
protected ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MZ100;
|
protected static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MZ100;
|
||||||
protected ThingTypeUID BRIDGE_TYPE_UID = WemoBindingConstants.THING_TYPE_BRIDGE;
|
protected static final ThingTypeUID BRIDGE_TYPE_UID = WemoBindingConstants.THING_TYPE_BRIDGE;
|
||||||
protected String WEMO_BRIDGE_ID = BRIDGE_TYPE_UID.getId();
|
protected static final String WEMO_BRIDGE_ID = BRIDGE_TYPE_UID.getId();
|
||||||
protected String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
|
protected static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
|
||||||
protected String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
protected static final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
|
||||||
|
|
||||||
private final String WEMO_LIGHT_ID = THING_TYPE_UID.getId();
|
private static final String WEMO_LIGHT_ID = THING_TYPE_UID.getId();
|
||||||
|
|
||||||
// UPnP service information
|
// UPnP service information
|
||||||
protected String DEVICE_MODEL_NAME = WEMO_LIGHT_ID;
|
protected static final String DEVICE_MODEL_NAME = WEMO_LIGHT_ID;
|
||||||
protected String SERVICE_ID = "bridge";
|
protected static final String SERVICE_ID = "bridge";
|
||||||
protected String SERVICE_NUMBER = "1";
|
protected static final String SERVICE_NUMBER = "1";
|
||||||
protected String SERVLET_URL = DEVICE_CONTROL_PATH + SERVICE_ID + SERVICE_NUMBER;
|
protected static final String SERVLET_URL = DEVICE_CONTROL_PATH + SERVICE_ID + SERVICE_NUMBER;
|
||||||
|
|
||||||
private Bridge bridge;
|
private Bridge bridge;
|
||||||
|
|
||||||
|
@ -71,8 +70,7 @@ public class GenericWemoLightOSGiTestParent extends GenericWemoOSGiTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType,
|
protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType) {
|
||||||
WemoHttpCall wemoHttpCaller) {
|
|
||||||
Configuration configuration = new Configuration();
|
Configuration configuration = new Configuration();
|
||||||
configuration.put(WemoBindingConstants.DEVICE_ID, WEMO_LIGHT_ID);
|
configuration.put(WemoBindingConstants.DEVICE_ID, WEMO_LIGHT_ID);
|
||||||
|
|
||||||
|
@ -91,7 +89,6 @@ public class GenericWemoLightOSGiTestParent extends GenericWemoOSGiTest {
|
||||||
ThingHandler handler = thing.getHandler();
|
ThingHandler handler = thing.getHandler();
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
AbstractWemoHandler h = (AbstractWemoHandler) handler;
|
AbstractWemoHandler h = (AbstractWemoHandler) handler;
|
||||||
h.setWemoHttpCaller(wemoHttpCaller);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return thing;
|
return thing;
|
||||||
|
|
|
@ -37,8 +37,10 @@ import org.jupnp.model.types.DeviceType;
|
||||||
import org.jupnp.model.types.ServiceId;
|
import org.jupnp.model.types.ServiceId;
|
||||||
import org.jupnp.model.types.ServiceType;
|
import org.jupnp.model.types.ServiceType;
|
||||||
import org.jupnp.model.types.UDN;
|
import org.jupnp.model.types.UDN;
|
||||||
|
import org.mockito.Mockito;
|
||||||
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
import org.openhab.binding.wemo.internal.WemoBindingConstants;
|
||||||
import org.openhab.binding.wemo.internal.handler.AbstractWemoHandler;
|
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.binding.wemo.internal.http.WemoHttpCall;
|
||||||
import org.openhab.core.config.core.Configuration;
|
import org.openhab.core.config.core.Configuration;
|
||||||
import org.openhab.core.io.transport.upnp.UpnpIOService;
|
import org.openhab.core.io.transport.upnp.UpnpIOService;
|
||||||
|
@ -52,7 +54,6 @@ import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingRegistry;
|
import org.openhab.core.thing.ThingRegistry;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.ThingUID;
|
import org.openhab.core.thing.ThingUID;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
|
||||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||||
import org.openhab.core.thing.type.ChannelKind;
|
import org.openhab.core.thing.type.ChannelKind;
|
||||||
|
@ -69,35 +70,39 @@ import org.openhab.core.thing.type.ChannelTypeUID;
|
||||||
*/
|
*/
|
||||||
public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
|
public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
|
||||||
|
|
||||||
public static MockUpnpService mockUpnpService;
|
|
||||||
public static final String DEVICE_MANUFACTURER = "Belkin";
|
public static final String DEVICE_MANUFACTURER = "Belkin";
|
||||||
|
|
||||||
// This port is included in the run configuration
|
// This port is included in the run configuration
|
||||||
private final int ORG_OSGI_SERVICE_HTTP_PORT = 9090;
|
private static final int ORG_OSGI_SERVICE_HTTP_PORT = 9090;
|
||||||
|
|
||||||
// Thing information
|
// Thing information
|
||||||
protected String TEST_THING_ID = "TestThing";
|
protected static final String TEST_THING_ID = "TestThing";
|
||||||
|
|
||||||
// UPnP Device information
|
// UPnP Device information
|
||||||
public static String DEVICE_UDN = "Test-1_0-22124";
|
public static final String DEVICE_UDN = "Test-1_0-22124";
|
||||||
|
|
||||||
private final String DEVICE_TYPE = "Test";
|
private static final String DEVICE_TYPE = "Test";
|
||||||
private final int DEVICE_VERSION = 1;
|
private static final int DEVICE_VERSION = 1;
|
||||||
private final String DEVICE_URL = "http://127.0.0.1:" + ORG_OSGI_SERVICE_HTTP_PORT;
|
private static final String DEVICE_URL = "http://127.0.0.1:" + ORG_OSGI_SERVICE_HTTP_PORT;
|
||||||
private final String DEVICE_DESCRIPTION_PATH = "/setup.xml";
|
private static final String DEVICE_DESCRIPTION_PATH = "/setup.xml";
|
||||||
|
|
||||||
protected final String DEVICE_FRIENDLY_NAME = "WeMo Test";
|
protected static final String DEVICE_FRIENDLY_NAME = "WeMo Test";
|
||||||
protected final String DEVICE_CONTROL_PATH = "/upnp/control/";
|
protected static final String DEVICE_CONTROL_PATH = "/upnp/control/";
|
||||||
protected final ChannelTypeUID DEFAULT_CHANNEL_TYPE_UID = new ChannelTypeUID(
|
protected static final ChannelTypeUID DEFAULT_CHANNEL_TYPE_UID = new ChannelTypeUID(
|
||||||
WemoBindingConstants.BINDING_ID + ":channelType");
|
WemoBindingConstants.BINDING_ID + ":channelType");
|
||||||
|
|
||||||
protected ManagedThingProvider managedThingProvider;
|
protected ManagedThingProvider managedThingProvider;
|
||||||
protected UpnpIOService upnpIOService;
|
protected UpnpIOService upnpIOService;
|
||||||
protected ThingRegistry thingRegistry;
|
protected ThingRegistry thingRegistry;
|
||||||
|
|
||||||
|
protected WemoHttpCall mockCaller;
|
||||||
|
protected MockUpnpService mockUpnpService;
|
||||||
|
|
||||||
protected Thing thing;
|
protected Thing thing;
|
||||||
|
|
||||||
protected void setUpServices() throws IOException {
|
protected void setUpServices() throws IOException {
|
||||||
|
WemoUtil.serviceAvailableFunction = (host, port) -> true;
|
||||||
|
|
||||||
// StorageService is required from the ManagedThingProvider
|
// StorageService is required from the ManagedThingProvider
|
||||||
VolatileStorageService volatileStorageService = new VolatileStorageService();
|
VolatileStorageService volatileStorageService = new VolatileStorageService();
|
||||||
registerService(volatileStorageService);
|
registerService(volatileStorageService);
|
||||||
|
@ -117,14 +122,17 @@ public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
|
||||||
upnpIOService = getService(UpnpIOService.class);
|
upnpIOService = getService(UpnpIOService.class);
|
||||||
assertThat(upnpIOService, is(notNullValue()));
|
assertThat(upnpIOService, is(notNullValue()));
|
||||||
|
|
||||||
|
mockCaller = Mockito.spy(new WemoHttpCall());
|
||||||
|
WemoHttpCallFactory wemoHttpCallFactory = () -> mockCaller;
|
||||||
|
registerService(wemoHttpCallFactory, WemoHttpCallFactory.class.getName());
|
||||||
|
|
||||||
ChannelTypeProvider channelTypeProvider = mock(ChannelTypeProvider.class);
|
ChannelTypeProvider channelTypeProvider = mock(ChannelTypeProvider.class);
|
||||||
when(channelTypeProvider.getChannelType(any(ChannelTypeUID.class), any(Locale.class))).thenReturn(
|
when(channelTypeProvider.getChannelType(any(ChannelTypeUID.class), any(Locale.class))).thenReturn(
|
||||||
ChannelTypeBuilder.state(DEFAULT_CHANNEL_TYPE_UID, "label", CoreItemFactory.SWITCH).build());
|
ChannelTypeBuilder.state(DEFAULT_CHANNEL_TYPE_UID, "label", CoreItemFactory.SWITCH).build());
|
||||||
registerService(channelTypeProvider);
|
registerService(channelTypeProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType,
|
protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType) {
|
||||||
WemoHttpCall wemoHttpCaller) {
|
|
||||||
Configuration configuration = new Configuration();
|
Configuration configuration = new Configuration();
|
||||||
configuration.put(WemoBindingConstants.UDN, DEVICE_UDN);
|
configuration.put(WemoBindingConstants.UDN, DEVICE_UDN);
|
||||||
|
|
||||||
|
@ -138,13 +146,6 @@ public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
managedThingProvider.add(thing);
|
managedThingProvider.add(thing);
|
||||||
|
|
||||||
ThingHandler handler = thing.getHandler();
|
|
||||||
if (handler != null) {
|
|
||||||
AbstractWemoHandler h = (AbstractWemoHandler) handler;
|
|
||||||
h.setWemoHttpCaller(wemoHttpCaller);
|
|
||||||
}
|
|
||||||
|
|
||||||
return thing;
|
return thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +154,8 @@ public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
|
||||||
UDN udn = new UDN(DEVICE_UDN);
|
UDN udn = new UDN(DEVICE_UDN);
|
||||||
URL deviceURL = new URL(DEVICE_URL + DEVICE_DESCRIPTION_PATH);
|
URL deviceURL = new URL(DEVICE_URL + DEVICE_DESCRIPTION_PATH);
|
||||||
|
|
||||||
RemoteDeviceIdentity identity = new RemoteDeviceIdentity(udn, WemoBindingConstants.SUBSCRIPTION_DURATION,
|
RemoteDeviceIdentity identity = new RemoteDeviceIdentity(udn,
|
||||||
deviceURL, new byte[1], null);
|
WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS, deviceURL, new byte[1], null);
|
||||||
DeviceType type = new DeviceType(DEVICE_MANUFACTURER, DEVICE_TYPE, DEVICE_VERSION);
|
DeviceType type = new DeviceType(DEVICE_MANUFACTURER, DEVICE_TYPE, DEVICE_VERSION);
|
||||||
|
|
||||||
ManufacturerDetails manufacturerDetails = new ManufacturerDetails(DEVICE_MANUFACTURER);
|
ManufacturerDetails manufacturerDetails = new ManufacturerDetails(DEVICE_MANUFACTURER);
|
||||||
|
|
Loading…
Reference in New Issue