import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* @author Hans-Jörg Merk - Initial contribution
* @author Mihir Patil - Added standby switch
*/
+@NonNullByDefault
public class WemoBindingConstants {
public static final String BINDING_ID = "wemo";
public static final String UDN = "udn";
public static final String DEVICE_ID = "deviceID";
public static final String POLLINGINTERVALL = "pollingInterval";
-
- public static final int SUBSCRIPTION_DURATION = 600;
+ public static final int DEFAULT_REFRESH_INTERVALL_SECONDS = 60;
+ public static final int SUBSCRIPTION_DURATION_SECONDS = 600;
public static final int LINK_DISCOVERY_SERVICE_INITIAL_DELAY = 5;
public static final String HTTP_CALL_CONTENT_HEADER = "text/xml; charset=utf-8";
import java.util.Map;
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.handler.WemoBridgeHandler;
import org.openhab.binding.wemo.internal.handler.WemoCoffeeHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
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.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author Hans-Jörg Merk - Initial contribution
* @author Kai Kreuzer - some refactoring for performance and simplification
*/
+@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.wemo")
public class WemoHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(WemoHandlerFactory.class);
- private UpnpIOService upnpIOService;
-
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = WemoBindingConstants.SUPPORTED_THING_TYPES;
+ private UpnpIOService upnpIOService;
+ private @Nullable WemoHttpCallFactory wemoHttpCallFactory;
+
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES.contains(thingTypeUID);
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
- @SuppressWarnings({ "null", "unused" })
- @Override
- 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;
+ @Activate
+ public WemoHandlerFactory(final @Reference UpnpIOService upnpIOService) {
+ this.upnpIOService = upnpIOService;
}
- @Reference
- protected void setUpnpIOService(UpnpIOService upnpIOService) {
- this.upnpIOService = upnpIOService;
+ @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
+ public void setWemoHttpCallFactory(WemoHttpCallFactory wemoHttpCallFactory) {
+ this.wemoHttpCallFactory = wemoHttpCallFactory;
+ }
+
+ public void unsetWemoHttpCallFactory(WemoHttpCallFactory wemoHttpCallFactory) {
+ this.wemoHttpCallFactory = null;
}
- protected void unsetUpnpIOService(UpnpIOService upnpIOService) {
- this.upnpIOService = 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
--- /dev/null
+/**
+ * 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();
+}
--- /dev/null
+/**
+ * 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;
+ }
+}
import java.util.Map;
import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.jupnp.model.meta.RemoteDevice;
import org.openhab.binding.wemo.internal.WemoBindingConstants;
* @author Kai Kreuzer - some refactoring for performance and simplification
*
*/
+@NonNullByDefault
@Component(service = UpnpDiscoveryParticipant.class)
public class WemoDiscoveryParticipant implements UpnpDiscoveryParticipant {
}
@Override
- public DiscoveryResult createResult(RemoteDevice device) {
+ public @Nullable DiscoveryResult createResult(RemoteDevice device) {
ThingUID uid = getThingUID(device);
if (uid != null) {
Map<String, Object> properties = new HashMap<>(2);
}
@Override
- public ThingUID getThingUID(@Nullable RemoteDevice device) {
+ public @Nullable ThingUID getThingUID(@Nullable RemoteDevice device) {
if (device != null) {
if (device.getDetails().getManufacturerDetails().getManufacturer() != null) {
if (device.getDetails().getManufacturerDetails().getManufacturer().toUpperCase().contains("BELKIN")) {
*/
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.model.message.header.RootDeviceHeader;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
* @author Hans-Jörg Merk - Initial contribution
*
*/
+@NonNullByDefault
@Component(service = DiscoveryService.class, configurationPid = "discovery.wemo")
public class WemoDiscoveryService extends AbstractDiscoveryService {
super(5);
}
- private UpnpService upnpService;
+ private @Nullable UpnpService upnpService;
@Reference
protected void setUpnpService(UpnpService upnpService) {
package org.openhab.binding.wemo.internal.discovery;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.io.StringReader;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.commons.lang3.StringEscapeUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.wemo.internal.handler.WemoBridgeHandler;
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
* @author Hans-Jörg Merk - Initial contribution
*
*/
+@NonNullByDefault
public class WemoLinkDiscoveryService extends AbstractDiscoveryService implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoLinkDiscoveryService.class);
/**
* Schedule for scanning
*/
- private ScheduledFuture<?> scanningJob;
+ private @Nullable ScheduledFuture<?> scanningJob;
/**
* The Upnp service
public WemoLinkDiscoveryService(WemoBridgeHandler wemoBridgeHandler, UpnpIOService upnpIOService,
WemoHttpCall wemoHttpCaller) {
super(SEARCH_TIME);
+ this.service = upnpIOService;
this.wemoBridgeHandler = wemoBridgeHandler;
this.wemoHttpCaller = wemoHttpCaller;
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
-
this.scanningRunnable = new WemoLinkScan();
- if (wemoBridgeHandler == null) {
- logger.warn("no bridge handler for scan given");
- }
this.activate(null);
}
URL descriptorURL = service.getDescriptorURL(this);
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 endDeviceRequest = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
logger.trace("endDeviceRequest answered '{}'", endDeviceRequest);
try {
- String stringParser = StringUtils.substringBetween(endDeviceRequest, "<DeviceLists>",
- "</DeviceLists>");
+ String stringParser = substringBetween(endDeviceRequest, "<DeviceLists>", "</DeviceLists>");
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
// check if there are already paired devices with WeMo Link
if ("0".equals(stringParser)) {
protected void startBackgroundDiscovery() {
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,
LINK_DISCOVERY_SERVICE_INITIAL_DELAY, SCAN_INTERVAL, TimeUnit.SECONDS);
} else {
protected void stopBackgroundDiscovery() {
logger.debug("Stop WeMo device background discovery");
- if (scanningJob != null && !scanningJob.isCancelled()) {
- scanningJob.cancel(true);
- scanningJob = null;
+ ScheduledFuture<?> job = scanningJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ scanningJob = null;
}
@Override
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
}
@Override
- public void onValueReceived(String variable, String value, String service) {
+ public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
}
@Override
*/
package org.openhab.binding.wemo.internal.handler;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.wemo.internal.http.WemoHttpCall;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.binding.BaseThingHandler;
/**
- *
- * @author Stefan Triller
- *
+ * @author Stefan Triller - Initial contribution
*/
+@NonNullByDefault
public abstract class AbstractWemoHandler extends BaseThingHandler {
- public AbstractWemoHandler(Thing thing) {
- super(thing);
- }
-
protected WemoHttpCall wemoHttpCaller;
- public void setWemoHttpCaller(WemoHttpCall wemoHttpCaller) {
+ public AbstractWemoHandler(Thing thing, WemoHttpCall wemoHttpCaller) {
+ super(thing);
this.wemoHttpCaller = wemoHttpCaller;
}
}
import java.util.Collections;
import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
*
* @author Hans-Jörg Merk - Initial contribution
*/
+@NonNullByDefault
public class WemoBridgeHandler extends BaseBridgeHandler {
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.io.StringReader;
import java.math.BigDecimal;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.commons.lang3.StringEscapeUtils;
-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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
* @author Hans-Jörg Merk - Initial contribution
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
*/
-
+@NonNullByDefault
public class WemoCoffeeHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoCoffeeHandler.class);
private Map<String, Boolean> subscriptionState = new HashMap<>();
- protected static final int SUBSCRIPTION_DURATION = 600;
-
private UpnpIOService service;
- /**
- * The default refresh interval in Seconds.
- */
- private final int REFRESH_INTERVAL = 60;
+ private WemoHttpCall wemoCall;
- private ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = new Runnable() {
}
};
- public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
- super(thing);
+ public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+ super(thing, wemoHttpCaller);
- this.wemoHttpCaller = wemoHttpcaller;
+ this.wemoCall = wemoHttpCaller;
+ this.service = upnpIOService;
logger.debug("Creating a WemoCoffeeHandler V0.4 for thing '{}'", getThing().getUID());
-
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
public void dispose() {
logger.debug("WeMoCoffeeHandler disposed.");
- removeSubscription();
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+ removeSubscription();
}
@Override
+ "<attribute><name>Cleaning</name><value>NULL</value></attribute></attributeList>"
+ "</u:SetAttributes>" + "</s:Body>" + "</s:Envelope>";
- String wemoURL = getWemoURL("deviceevent");
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
updateState(CHANNEL_STATE, OnOffType.ON);
State newMode = new StringType("Brewing");
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
- logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
- subscriptionState.put(service, succeeded);
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
+ if (service != null) {
+ logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
+ succeeded ? "succeeded" : "failed");
+ subscriptionState.put(service, succeeded);
+ }
}
@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.
}
logger.debug("Checking WeMo GENA subscription for '{}'", this);
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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
} else {
if (service.isRegistered(this)) {
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);
service.removeSubscription(this, subscription);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = REFRESH_INTERVAL;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("pollingInterval");
if (refreshConfig != null) {
refreshInterval = ((BigDecimal) refreshConfig).intValue();
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, actionService);
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
try {
- String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
- "</attributeList>");
+ String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
// Due to Belkins bad response formatting, we need to run this twice.
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
logger.trace("CoffeeMaker response '{}' for device '{}' received", stringParser,
getThing().getUID());
switch (attributeName) {
case "Mode":
State newMode = new StringType("Brewing");
+ State newAttributeValue;
+
switch (attributeValue) {
case "0":
updateState(CHANNEL_STATE, OnOffType.ON);
}
break;
case "ModeTime":
- if (attributeValue != null) {
- State newAttributeValue = new DecimalType(attributeValue);
- updateState(CHANNEL_MODETIME, newAttributeValue);
- }
+ newAttributeValue = new DecimalType(attributeValue);
+ updateState(CHANNEL_MODETIME, newAttributeValue);
break;
case "TimeRemaining":
- if (attributeValue != null) {
- State newAttributeValue = new DecimalType(attributeValue);
- updateState(CHANNEL_TIMEREMAINING, newAttributeValue);
- }
+ newAttributeValue = new DecimalType(attributeValue);
+ updateState(CHANNEL_TIMEREMAINING, newAttributeValue);
break;
case "WaterLevelReached":
- if (attributeValue != null) {
- State newAttributeValue = new DecimalType(attributeValue);
- updateState(CHANNEL_WATERLEVELREACHED, newAttributeValue);
- }
+ newAttributeValue = new DecimalType(attributeValue);
+ updateState(CHANNEL_WATERLEVELREACHED, newAttributeValue);
break;
case "CleanAdvise":
- if (attributeValue != null) {
- State newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF
- : OnOffType.ON;
- updateState(CHANNEL_CLEANADVISE, newAttributeValue);
- }
+ newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
+ updateState(CHANNEL_CLEANADVISE, newAttributeValue);
break;
case "FilterAdvise":
- if (attributeValue != null) {
- State newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF
- : OnOffType.ON;
- updateState(CHANNEL_FILTERADVISE, newAttributeValue);
- }
+ newAttributeValue = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
+ updateState(CHANNEL_FILTERADVISE, newAttributeValue);
break;
case "Brewed":
- if (attributeValue != null) {
- State newAttributeValue = getDateTimeState(attributeValue);
- if (newAttributeValue != null) {
- updateState(CHANNEL_BREWED, newAttributeValue);
- }
+ newAttributeValue = getDateTimeState(attributeValue);
+ if (newAttributeValue != null) {
+ updateState(CHANNEL_BREWED, newAttributeValue);
}
break;
case "LastCleaned":
- if (attributeValue != null) {
- State newAttributeValue = getDateTimeState(attributeValue);
- if (newAttributeValue != null) {
- updateState(CHANNEL_LASTCLEANED, newAttributeValue);
- }
+ newAttributeValue = getDateTimeState(attributeValue);
+ if (newAttributeValue != null) {
+ updateState(CHANNEL_LASTCLEANED, newAttributeValue);
}
break;
}
}
}
- @SuppressWarnings("null")
- 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.error("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 brewed '{}' received", dateTimeState);
- return dateTimeState;
- }
- }
- return null;
- }
-
- 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;
+ public @Nullable State getDateTimeState(String attributeValue) {
+ long value = 0;
+ try {
+ value = Long.parseLong(attributeValue);
+ } catch (NumberFormatException e) {
+ logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
+ 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);
+ return dateTimeState;
}
public static String getCharacterDataFromElement(Element e) {
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.concurrent.ScheduledFuture;
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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
*
* @author Hans-Jörg Merk - Initial contribution;
*/
-
+@NonNullByDefault
public class WemoCrockpotHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoCrockpotHandler.class);
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, String> stateMap = Collections.synchronizedMap(new HashMap<>());
private UpnpIOService service;
- private ScheduledFuture<?> refreshJob;
+ private WemoHttpCall wemoCall;
+
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = () -> {
updateWemoState();
}
};
- public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
- super(thing);
+ public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+ super(thing, wemoHttpCaller);
- this.wemoHttpCaller = wemohttpCaller;
+ this.wemoCall = wemoHttpCaller;
+ this.service = upnpIOService;
logger.debug("Creating a WemoCrockpotHandler for thing '{}'", getThing().getUID());
-
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
public void dispose() {
logger.debug("WeMoCrockpotHandler disposed.");
- removeSubscription();
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+ removeSubscription();
}
@Override
+ "<s:Body>" + "<u:SetCrockpotState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<mode>"
+ mode + "</mode>" + "<time>" + time + "</time>" + "</u:SetCrockpotState>" + "</s:Body>"
+ "</s:Envelope>";
- String wemoURL = getWemoURL("basicevent");
+
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
if (wemoURL != null) {
- wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (RuntimeException e) {
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
- logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
- subscriptionState.put(service, succeeded);
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
+ if (service != null) {
+ logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
+ succeeded ? "succeeded" : "failed");
+ subscriptionState.put(service, succeeded);
+ }
}
@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,
this.getThing().getUID());
updateStatus(ThingStatus.ONLINE);
- this.stateMap.put(variable, value);
+ if (variable != null && value != null) {
+ this.stateMap.put(variable, value);
+ }
}
private synchronized void onSubscription() {
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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
if (service.isRegistered(this)) {
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);
service.removeSubscription(this, subscription);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL_SECONDS;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("refresh");
- refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVAL_SECONDS
+ refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVALL_SECONDS
: ((BigDecimal) refreshConfig).intValue();
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
}
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, actionService);
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
- String mode = StringUtils.substringBetween(wemoCallResponse, "<mode>", "</mode>");
- String time = StringUtils.substringBetween(wemoCallResponse, "<time>", "</time>");
- String coockedTime = StringUtils.substringBetween(wemoCallResponse, "<coockedTime>",
- "</coockedTime>");
-
- if (mode != null && time != null && coockedTime != null) {
- State newMode = new StringType(mode);
- State newCoockedTime = DecimalType.valueOf(coockedTime);
- switch (mode) {
- case "0":
- newMode = new StringType("OFF");
- break;
- case "50":
- newMode = new StringType("WARM");
- State warmTime = DecimalType.valueOf(time);
- updateState(CHANNEL_WARMCOOKTIME, warmTime);
- break;
- case "51":
- newMode = new StringType("LOW");
- State lowTime = DecimalType.valueOf(time);
- updateState(CHANNEL_LOWCOOKTIME, lowTime);
- break;
- case "52":
- newMode = new StringType("HIGH");
- State highTime = DecimalType.valueOf(time);
- updateState(CHANNEL_HIGHCOOKTIME, highTime);
- break;
- }
- updateState(CHANNEL_COOKMODE, newMode);
- updateState(CHANNEL_COOKEDTIME, newCoockedTime);
+ String mode = substringBetween(wemoCallResponse, "<mode>", "</mode>");
+ String time = substringBetween(wemoCallResponse, "<time>", "</time>");
+ String coockedTime = substringBetween(wemoCallResponse, "<coockedTime>", "</coockedTime>");
+
+ State newMode = new StringType(mode);
+ State newCoockedTime = DecimalType.valueOf(coockedTime);
+ switch (mode) {
+ case "0":
+ newMode = new StringType("OFF");
+ break;
+ case "50":
+ newMode = new StringType("WARM");
+ State warmTime = DecimalType.valueOf(time);
+ updateState(CHANNEL_WARMCOOKTIME, warmTime);
+ break;
+ case "51":
+ newMode = new StringType("LOW");
+ State lowTime = DecimalType.valueOf(time);
+ updateState(CHANNEL_LOWCOOKTIME, lowTime);
+ break;
+ case "52":
+ newMode = new StringType("HIGH");
+ State highTime = DecimalType.valueOf(time);
+ updateState(CHANNEL_HIGHCOOKTIME, highTime);
+ break;
}
+ updateState(CHANNEL_COOKMODE, newMode);
+ updateState(CHANNEL_COOKEDTIME, newCoockedTime);
}
}
} catch (RuntimeException e) {
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
public void onStatusChanged(boolean status) {
}
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.concurrent.ScheduledFuture;
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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
*
* @author Hans-Jörg Merk - Initial contribution
*/
-
+@NonNullByDefault
public class WemoDimmerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoDimmerHandler.class);
+
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DIMMER);
+
private Map<String, Boolean> subscriptionState = new HashMap<>();
private Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
- protected static final int SUBSCRIPTION_DURATION = 600;
+
private UpnpIOService service;
+ private WemoHttpCall wemoCall;
+
private int currentBrightness;
private int currentNightModeBrightness;
- private String currentNightModeState = null;
+ private @Nullable String currentNightModeState;
/**
* Set dimming stepsize to 5%
*/
private static final int DIM_STEPSIZE = 5;
- /**
- * The default refresh interval in Seconds.
- */
- private int DEFAULT_REFRESH_INTERVAL = 60;
- private ScheduledFuture<?> refreshJob;
+
+ private @Nullable ScheduledFuture<?> refreshJob;
private Runnable refreshRunnable = new Runnable() {
@Override
}
};
- public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
- super(thing);
- this.wemoHttpCaller = wemohttpCaller;
+ public WemoDimmerHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+ super(thing, wemoHttpCaller);
+
+ this.service = upnpIOService;
+ this.wemoCall = wemoHttpCaller;
+
logger.debug("Creating a WemoDimmerHandler for thing '{}'", getThing().getUID());
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
@Override
public void dispose() {
logger.debug("WeMoDimmerHandler disposed.");
- removeSubscription();
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+
+ removeSubscription();
}
@Override
String timeStamp = null;
switch (channelUID.getId()) {
case CHANNEL_BRIGHTNESS:
+ String binaryState = this.stateMap.get("BinaryState");
if (command instanceof OnOffType) {
value = command.equals(OnOffType.OFF) ? "0" : "1";
setBinaryState(action, argument, value);
value = "0";
argument = "BinaryState";
setBinaryState(action, argument, "0");
- } else if (this.stateMap.get("BinaryState").equals("0")) {
+ } else if ("0".equals(binaryState)) {
argument = "BinaryState";
setBinaryState(action, argument, "1");
}
value = "0";
argument = "BinaryState";
setBinaryState(action, argument, "0");
- } else if (this.stateMap.get("BinaryState").equals("0")) {
+ } else if ("0".equals(binaryState)) {
argument = "BinaryState";
setBinaryState(action, argument, "1");
}
logger.info("timestamp '{}' created", timeStamp);
String faderSeconds = null;
String faderEnabled = null;
- String[] splitFader = this.stateMap.get("fader").split(":");
- if (splitFader[0] != null) {
- faderSeconds = splitFader[0];
- }
- if (splitFader[0] != null) {
- faderEnabled = splitFader[2];
+ String fader = this.stateMap.get("fader");
+ if (fader != null) {
+ String[] splitFader = fader.split(":");
+ if (splitFader[0] != null) {
+ faderSeconds = splitFader[0];
+ }
+ if (splitFader[0] != null) {
+ faderEnabled = splitFader[2];
+ }
}
if (faderSeconds != null && faderEnabled != null) {
if (command.equals(OnOffType.ON)) {
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
- logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
- subscriptionState.put(service, succeeded);
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
+ if (service != null) {
+ logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
+ succeeded ? "succeeded" : "failed");
+ subscriptionState.put(service, succeeded);
+ }
}
@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 '{}'",
new Object[] { variable, value, service, this.getThing().getUID() });
updateStatus(ThingStatus.ONLINE);
- this.stateMap.put(variable, value);
- switch (variable) {
- case "BinaryState":
- State state = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
- logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
- updateState(CHANNEL_BRIGHTNESS, state);
- if (state.equals(OnOffType.OFF)) {
- updateState(CHANNEL_TIMERSTART, OnOffType.OFF);
- }
- break;
- case "brightness":
- 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);
+ if (variable != null && value != null) {
+ this.stateMap.put(variable, value);
+ }
+ if (variable != null && value != null) {
+ switch (variable) {
+ case "BinaryState":
+ State state = value.equals("0") ? OnOffType.OFF : OnOffType.ON;
+ logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
+ updateState(CHANNEL_BRIGHTNESS, state);
+ if (state.equals(OnOffType.OFF)) {
+ updateState(CHANNEL_TIMERSTART, OnOffType.OFF);
}
- }
- 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());
- updateState(CHANNEL_STARTTIME, startTimeState);
- break;
- case "endTime":
- State endTimeState = getDateTimeState(value);
- logger.debug("endTimeState '{}' for device '{}' received", endTimeState, getThing().getUID());
- 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;
+ break;
+ case "brightness":
+ logger.debug("brightness '{}' for device '{}' received", value, getThing().getUID());
+ int newBrightnessValue = Integer.valueOf(value);
+ State newBrightnessState = new PercentType(newBrightnessValue);
+ String binaryState = this.stateMap.get("BinaryState");
+ if (binaryState != null) {
+ if (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);
+ }
+ }
+ 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;
+ }
+
}
}
if (service.isRegistered(this)) {
logger.debug("Checking WeMo GENA subscription for '{}'", this);
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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
} else {
logger.debug("Removing WeMo GENA subscription for '{}'", this);
if (service.isRegistered(this)) {
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);
service.removeSubscription(this, subscription);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("refresh");
if (refreshConfig != null) {
refreshInterval = ((BigDecimal) refreshConfig).intValue();
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
- value = StringUtils.substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
- if (value != null) {
- variable = "BinaryState";
- logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
- this.onValueReceived(variable, value, actionService + "1");
- }
- value = StringUtils.substringBetween(wemoCallResponse, "<brightness>", "</brightness>");
- if (value != null) {
- variable = "brightness";
- logger.trace("New brightness '{}' 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");
- }
+ value = substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
+ variable = "BinaryState";
+ logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<brightness>", "</brightness>");
+ variable = "brightness";
+ logger.trace("New brightness '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<fader>", "</fader>");
+ variable = "fader";
+ logger.trace("New fader value '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
}
}
} catch (Exception e) {
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:" + actionService + ":1\">" + "</u:"
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
logger.trace("GetNightModeConfiguration response '{}' for device '{}' received", wemoCallResponse,
getThing().getUID());
- value = StringUtils.substringBetween(wemoCallResponse, "<startTime>", "</startTime>");
- if (value != null) {
- variable = "startTime";
- logger.trace("New startTime '{}' for device '{}' received", value, getThing().getUID());
- this.onValueReceived(variable, value, actionService + "1");
- }
- value = StringUtils.substringBetween(wemoCallResponse, "<endTime>", "</endTime>");
- if (value != null) {
- variable = "endTime";
- logger.trace("New endTime '{}' for device '{}' received", value, getThing().getUID());
- this.onValueReceived(variable, value, actionService + "1");
- }
- value = StringUtils.substringBetween(wemoCallResponse, "<nightMode>", "</nightMode>");
- if (value != null) {
- variable = "nightMode";
- logger.trace("New nightMode state '{}' for device '{}' received", value, getThing().getUID());
- 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");
- }
+ value = substringBetween(wemoCallResponse, "<startTime>", "</startTime>");
+ variable = "startTime";
+ logger.trace("New startTime '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<endTime>", "</endTime>");
+ variable = "endTime";
+ logger.trace("New endTime '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<nightMode>", "</nightMode>");
+ variable = "nightMode";
+ logger.trace("New nightMode state '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<nightModeBrightness>", "</nightModeBrightness>");
+ variable = "nightModeBrightness";
+ logger.trace("New nightModeBrightness '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
}
}
} catch (Exception e) {
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;
- }
-
- @SuppressWarnings("null")
- 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;
- }
+ public @Nullable State getDateTimeState(String attributeValue) {
+ long value = 0;
+ try {
+ value = Long.parseLong(attributeValue);
+ } catch (NumberFormatException e) {
+ logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
+ 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);
+ return dateTimeState;
}
public void setBinaryState(String action, String argument, String value) {
+ "<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
+ ">" + 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) {
- logger.trace("About to send content to Dimmer {}", content);
- wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (Exception e) {
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
+ "<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
+ "</u:SetBinaryState>" + "</s:Body>" + "</s:Envelope>";
- String wemoURL = getWemoURL("basicevent");
+
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
+
if (wemoURL != null) {
- logger.trace("About to send content to Dimmer {}", content);
- wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (Exception e) {
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
package org.openhab.binding.wemo.internal.handler;
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.RoundingMode;
import java.net.URL;
import java.util.stream.Collectors;
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.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.UpnpIOService;
import org.openhab.core.library.types.DateTimeType;
* The {@link WemoHandler} is responsible for handling commands, which are
* 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 Stefan Bußweiler - Added new thing status handling
* @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType
* @author Mihir Patil - Added standby switch
*/
-
+@NonNullByDefault
public class WemoHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoHandler.class);
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
- // protected static final int SUBSCRIPTION_DURATION = WemoBindingConstants.SUBSCRIPTION_DURATION;
-
- private UpnpIOService service;
+ protected UpnpIOService service;
+ private WemoHttpCall wemoCall;
- /**
- * The default refresh interval in Seconds.
- */
- private final int DEFAULT_REFRESH_INTERVAL = 120;
-
- private ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = new Runnable() {
}
};
- public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
- super(thing);
+ public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+ super(thing, wemoHttpCaller);
- this.wemoHttpCaller = wemohttpCaller;
+ this.service = upnpIOService;
+ this.wemoCall = wemoHttpCaller;
logger.debug("Creating a WemoHandler for thing '{}'", getThing().getUID());
-
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
public void dispose() {
logger.debug("WeMoHandler disposed.");
- removeSubscription();
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+ removeSubscription();
}
@Override
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
+ "</s:Envelope>";
- String wemoURL = getWemoURL("basicevent");
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
if (wemoURL != null) {
- wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (Exception e) {
logger.error("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
- logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
- subscriptionState.put(service, succeeded);
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
+ if (service != null) {
+ logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
+ succeeded ? "succeeded" : "failed");
+ subscriptionState.put(service, succeeded);
+ }
}
- @SuppressWarnings("null")
@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 '{}'",
new Object[] { variable, value, service, this.getThing().getUID() });
updateStatus(ThingStatus.ONLINE);
- this.stateMap.put(variable, value);
+ if (variable != null && value != null) {
+ this.stateMap.put(variable, value);
+ }
if (getThing().getThingTypeUID().getId().equals("insight")) {
String insightParams = stateMap.get("InsightParams");
if (splitInsightParams[0] != null) {
OnOffType binaryState = null;
binaryState = splitInsightParams[0].equals("0") ? OnOffType.OFF : OnOffType.ON;
- if (binaryState != null) {
- logger.trace("New InsightParam binaryState '{}' for device '{}' received", binaryState,
- getThing().getUID());
- updateState(CHANNEL_STATE, binaryState);
- }
+ logger.trace("New InsightParam binaryState '{}' for device '{}' received", binaryState,
+ getThing().getUID());
+ updateState(CHANNEL_STATE, binaryState);
}
long lastChangedAt = 0;
}
State lastOnFor = DecimalType.valueOf(splitInsightParams[2]);
- if (lastOnFor != null) {
- logger.trace("New InsightParam lastOnFor '{}' for device '{}' received", lastOnFor,
- getThing().getUID());
- updateState(CHANNEL_LASTONFOR, lastOnFor);
- }
+ logger.trace("New InsightParam lastOnFor '{}' for device '{}' received", lastOnFor,
+ getThing().getUID());
+ updateState(CHANNEL_LASTONFOR, lastOnFor);
State onToday = DecimalType.valueOf(splitInsightParams[3]);
- if (onToday != null) {
- logger.trace("New InsightParam onToday '{}' for device '{}' received", onToday,
- getThing().getUID());
- updateState(CHANNEL_ONTODAY, onToday);
- }
+ logger.trace("New InsightParam onToday '{}' for device '{}' received", onToday, getThing().getUID());
+ updateState(CHANNEL_ONTODAY, onToday);
State onTotal = DecimalType.valueOf(splitInsightParams[4]);
- if (onTotal != null) {
- logger.trace("New InsightParam onTotal '{}' for device '{}' received", onTotal,
- getThing().getUID());
- updateState(CHANNEL_ONTOTAL, onTotal);
- }
+ logger.trace("New InsightParam onTotal '{}' for device '{}' received", onTotal, getThing().getUID());
+ updateState(CHANNEL_ONTOTAL, onTotal);
State timespan = DecimalType.valueOf(splitInsightParams[5]);
- if (timespan != null) {
- logger.trace("New InsightParam timespan '{}' for device '{}' received", timespan,
- getThing().getUID());
- updateState(CHANNEL_TIMESPAN, timespan);
- }
+ logger.trace("New InsightParam timespan '{}' for device '{}' received", timespan, getThing().getUID());
+ updateState(CHANNEL_TIMESPAN, timespan);
State averagePower = DecimalType.valueOf(splitInsightParams[6]); // natively given in W
- if (averagePower != null) {
- logger.trace("New InsightParam averagePower '{}' for device '{}' received", averagePower,
- getThing().getUID());
- updateState(CHANNEL_AVERAGEPOWER, averagePower);
- }
+ logger.trace("New InsightParam averagePower '{}' for device '{}' received", averagePower,
+ getThing().getUID());
+ updateState(CHANNEL_AVERAGEPOWER, averagePower);
BigDecimal currentMW = new BigDecimal(splitInsightParams[7]);
State currentPower = new DecimalType(currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
// mW to W
- if (currentPower != null) {
- logger.trace("New InsightParam currentPower '{}' for device '{}' received", currentPower,
- getThing().getUID());
- updateState(CHANNEL_CURRENTPOWER, currentPower);
- }
+ logger.trace("New InsightParam currentPower '{}' for device '{}' received", currentPower,
+ getThing().getUID());
+ updateState(CHANNEL_CURRENTPOWER, currentPower);
BigDecimal energyTodayMWMin = new BigDecimal(splitInsightParams[8]);
// recalculate mW-mins to Wh
State energyToday = new DecimalType(
energyTodayMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
- if (energyToday != null) {
- logger.trace("New InsightParam energyToday '{}' for device '{}' received", energyToday,
- getThing().getUID());
- updateState(CHANNEL_ENERGYTODAY, energyToday);
- }
+ logger.trace("New InsightParam energyToday '{}' for device '{}' received", energyToday,
+ getThing().getUID());
+ updateState(CHANNEL_ENERGYTODAY, energyToday);
BigDecimal energyTotalMWMin = new BigDecimal(splitInsightParams[9]);
// recalculate mW-mins to Wh
State energyTotal = new DecimalType(
energyTotalMWMin.divide(new BigDecimal(60000), RoundingMode.HALF_UP));
- if (energyTotal != null) {
- logger.trace("New InsightParam energyTotal '{}' for device '{}' received", energyTotal,
- getThing().getUID());
- updateState(CHANNEL_ENERGYTOTAL, energyTotal);
- }
+ logger.trace("New InsightParam energyTotal '{}' for device '{}' received", energyTotal,
+ getThing().getUID());
+ updateState(CHANNEL_ENERGYTOTAL, energyTotal);
BigDecimal standByLimitMW = new BigDecimal(splitInsightParams[10]);
State standByLimit = new DecimalType(standByLimitMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP)); // recalculate
// mW to W
- if (standByLimit != null) {
- logger.trace("New InsightParam standByLimit '{}' for device '{}' received", standByLimit,
- getThing().getUID());
- updateState(CHANNEL_STANDBYLIMIT, standByLimit);
- }
+ logger.trace("New InsightParam standByLimit '{}' for device '{}' received", standByLimit,
+ getThing().getUID());
+ updateState(CHANNEL_STANDBYLIMIT, standByLimit);
+
if (currentMW.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue() > standByLimitMW
.divide(new BigDecimal(1000), RoundingMode.HALF_UP).intValue()) {
updateState(CHANNEL_ONSTANDBY, OnOffType.OFF);
}
}
} else {
- State state = stateMap.get("BinaryState").equals("0") ? OnOffType.OFF : OnOffType.ON;
-
- logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
-
- if (state != null) {
+ String binaryState = stateMap.get("BinaryState");
+ if (binaryState != null) {
+ State state = binaryState.equals("0") ? OnOffType.OFF : OnOffType.ON;
+ logger.debug("State '{}' for device '{}' received", state, getThing().getUID());
if (getThing().getThingTypeUID().getId().equals("motion")) {
updateState(CHANNEL_MOTIONDETECTION, state);
if (state.equals(OnOffType.ON)) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
subscription = "insight1";
- 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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
}
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
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);
service.removeSubscription(this, subscription);
}
if (thingTypeUID.equals(THING_TYPE_INSIGHT)) {
subscription = "insight1";
- if ((subscriptionState.get(subscription) != null)
- && subscriptionState.get(subscription).booleanValue()) {
+ if (subscriptionState.get(subscription) != null) {
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
service.removeSubscription(this, subscription);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("refresh");
if (refreshConfig != null) {
refreshInterval = ((BigDecimal) refreshConfig).intValue();
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, actionService);
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
if (variable.equals("InsightParams")) {
- value = StringUtils.substringBetween(wemoCallResponse, "<InsightParams>", "</InsightParams>");
+ value = substringBetween(wemoCallResponse, "<InsightParams>", "</InsightParams>");
} else {
- value = StringUtils.substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
- }
- if (value != null) {
- logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
- this.onValueReceived(variable, value, actionService + "1");
+ value = substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
}
+ logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
+ this.onValueReceived(variable, value, actionService + "1");
}
}
} catch (Exception e) {
}
}
- 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
public void onStatusChanged(boolean status) {
}
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import org.apache.commons.lang3.StringEscapeUtils;
-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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
*
* @author Hans-Jörg Merk - Initial contribution;
*/
-
+@NonNullByDefault
public class WemoHolmesHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoHolmesHandler.class);
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_MINS = FILTER_LIFE_DAYS * 24 * 60;
private final Map<String, Boolean> subscriptionState = new HashMap<>();
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
private UpnpIOService service;
+ private WemoHttpCall wemoCall;
- private ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = () -> {
if (!isUpnpDeviceRegistered()) {
}
};
- public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemohttpCaller) {
- super(thing);
+ public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
+ super(thing, wemoHttpCaller);
- this.wemoHttpCaller = wemohttpCaller;
+ this.service = upnpIOService;
+ this.wemoCall = wemoHttpCaller;
logger.debug("Creating a WemoHolmesHandler for thing '{}'", getThing().getUID());
-
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
public void dispose() {
logger.debug("WemoHolmesHandler disposed.");
- removeSubscription();
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+ removeSubscription();
}
@Override
+ "<attributeList><attribute><name>" + attribute + "</name><value>" + value
+ "</value></attribute></attributeList>" + "</u:SetAttributes>" + "</s:Body>"
+ "</s:Envelope>";
- String wemoURL = getWemoURL("deviceevent");
+
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "deviceevent");
if (wemoURL != null) {
- wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (RuntimeException e) {
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
- logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service, succeeded ? "succeeded" : "failed");
- subscriptionState.put(service, succeeded);
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
+ if (service != null) {
+ logger.debug("WeMo {}: Subscription to service {} {}", getUDN(), service,
+ succeeded ? "succeeded" : "failed");
+ subscriptionState.put(service, succeeded);
+ }
}
@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,
this.getThing().getUID());
updateStatus(ThingStatus.ONLINE);
- this.stateMap.put(variable, value);
+ if (variable != null && value != null) {
+ this.stateMap.put(variable, value);
+ }
}
private synchronized void onSubscription() {
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);
- service.addSubscription(this, subscription, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(subscription, true);
}
if (service.isRegistered(this)) {
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);
service.removeSubscription(this, subscription);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL_SECONDS;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("refresh");
- refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVAL_SECONDS
+ refreshInterval = refreshConfig == null ? DEFAULT_REFRESH_INTERVALL_SECONDS
: ((BigDecimal) refreshConfig).intValue();
refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
}
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, actionService);
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
logger.trace("State response '{}' for device '{}' received", wemoCallResponse, getThing().getUID());
- String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
- "</attributeList>");
+ String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
// Due to Belkins bad response formatting, we need to run this twice.
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
logger.trace("AirPurifier response '{}' for device '{}' received", stringParser,
getThing().getUID());
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) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.math.BigDecimal;
import java.net.URL;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang3.StringEscapeUtils;
-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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
*
* @author Hans-Jörg Merk - Initial contribution
*/
+@NonNullByDefault
public class WemoLightHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoLightHandler.class);
private Map<String, Boolean> subscriptionState = new HashMap<>();
private UpnpIOService service;
+ private WemoHttpCall wemoCall;
- private WemoBridgeHandler wemoBridgeHandler;
+ private @Nullable WemoBridgeHandler wemoBridgeHandler;
- private String wemoLightID;
+ private @Nullable String wemoLightID;
private int currentBrightness;
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.
*/
private static final int DEFAULT_REFRESH_INITIAL_DELAY = 15;
- private ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = new Runnable() {
};
public WemoLightHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpcaller) {
- super(thing);
+ super(thing, wemoHttpcaller);
- this.wemoHttpCaller = wemoHttpcaller;
-
- if (upnpIOService != null) {
- logger.debug("UPnPIOService '{}'", upnpIOService);
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
+ this.service = upnpIOService;
+ this.wemoCall = wemoHttpcaller;
}
@Override
// initialize() is only called if the required parameter 'deviceID' is available
wemoLightID = (String) getConfig().get(DEVICE_ID);
- if (getBridge() != null) {
- logger.debug("Initializing WemoLightHandler for LightID '{}'", wemoLightID);
- if (getBridge().getStatus() == ThingStatus.ONLINE) {
- updateStatus(ThingStatus.ONLINE);
- onSubscription();
- onUpdate();
- } else {
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
- }
+ final Bridge bridge = getBridge();
+ if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
+ updateStatus(ThingStatus.ONLINE);
+ onSubscription();
+ onUpdate();
} else {
- updateStatus(ThingStatus.OFFLINE);
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
}
}
onUpdate();
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE);
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
}
}
public void dispose() {
logger.debug("WeMoLightHandler disposed.");
- removeSubscription();
-
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
+ removeSubscription();
}
- private synchronized WemoBridgeHandler getWemoBridgeHandler() {
- if (this.wemoBridgeHandler == null) {
- Bridge bridge = getBridge();
- if (bridge == null) {
- logger.error("Required bridge not defined for device {}.", wemoLightID);
- return null;
- }
- ThingHandler handler = bridge.getHandler();
- if (handler instanceof WemoBridgeHandler) {
- this.wemoBridgeHandler = (WemoBridgeHandler) handler;
- } else {
- logger.debug("No available bridge handler found for {} bridge {} .", wemoLightID, bridge.getUID());
- return null;
- }
+ private synchronized @Nullable WemoBridgeHandler getWemoBridgeHandler() {
+ Bridge bridge = getBridge();
+ if (bridge == null) {
+ logger.error("Required bridge not defined for device {}.", wemoLightID);
+ return null;
+ }
+ ThingHandler handler = bridge.getHandler();
+ if (handler instanceof WemoBridgeHandler) {
+ this.wemoBridgeHandler = (WemoBridgeHandler) handler;
+ } else {
+ logger.debug("No available bridge handler found for {} bridge {} .", wemoLightID, bridge.getUID());
+ return null;
}
return this.wemoBridgeHandler;
}
+ "</CapabilityValue></DeviceStatus>" + "</DeviceStatusList>"
+ "</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) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
if (capability.equals("10008")) {
OnOffType binaryState = null;
}
@Override
- public String getUDN() {
+ public @Nullable String getUDN() {
WemoBridgeHandler wemoBridge = getWemoBridgeHandler();
if (wemoBridge == null) {
logger.debug("wemoBridgeHandler not found");
+ "<s:Body>" + "<u:GetDeviceStatus xmlns:u=\"urn:Belkin:service:bridge:1\">" + "<DeviceIDs>"
+ wemoLightID + "</DeviceIDs>" + "</u:GetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
- String wemoURL = getWemoURL();
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "bridge");
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
- wemoCallResponse = StringEscapeUtils.unescapeXml(wemoCallResponse);
- String response = StringUtils.substringBetween(wemoCallResponse, "<CapabilityValue>",
- "</CapabilityValue>");
+ wemoCallResponse = unescapeXml(wemoCallResponse);
+ String response = substringBetween(wemoCallResponse, "<CapabilityValue>", "</CapabilityValue>");
logger.trace("wemoNewLightState = {}", response);
String[] splitResponse = response.split(",");
if (splitResponse[0] != null) {
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
}
@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 '{}'",
new Object[] { variable, value, service, this.getThing().getUID() });
- String capabilityId = StringUtils.substringBetween(value, "<CapabilityId>", "</CapabilityId>");
- String newValue = StringUtils.substringBetween(value, "<Value>", "</Value>");
+ String capabilityId = substringBetween(value, "<CapabilityId>", "</CapabilityId>");
+ String newValue = substringBetween(value, "<Value>", "</Value>");
switch (capabilityId) {
case "10006":
OnOffType binaryState = null;
if (service.isRegistered(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);
- service.addSubscription(this, SUBSCRIPTION, SUBSCRIPTION_DURATION);
+ service.addSubscription(this, SUBSCRIPTION, SUBSCRIPTION_DURATION_SECONDS);
subscriptionState.put(SUBSCRIPTION, true);
}
} else {
if (service.isRegistered(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);
service.removeSubscription(this, SUBSCRIPTION);
}
}
private synchronized void onUpdate() {
- if (refreshJob == null || refreshJob.isCancelled()) {
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL;
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
Object refreshConfig = config.get("refresh");
if (refreshConfig != null) {
refreshInterval = ((BigDecimal) refreshConfig).intValue();
private boolean isUpnpDeviceRegistered() {
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;
- }
}
package org.openhab.binding.wemo.internal.handler;
import static org.openhab.binding.wemo.internal.WemoBindingConstants.*;
+import static org.openhab.binding.wemo.internal.WemoUtil.*;
import java.io.StringReader;
import java.math.BigDecimal;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.commons.lang3.StringEscapeUtils;
-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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOParticipant;
*
* @author Hans-Jörg Merk - Initial contribution
*/
-
+@NonNullByDefault
public class WemoMakerHandler extends AbstractWemoHandler implements UpnpIOParticipant {
private final Logger logger = LoggerFactory.getLogger(WemoMakerHandler.class);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_MAKER);
private UpnpIOService service;
+ private WemoHttpCall wemoCall;
- /**
- * The default refresh interval in Seconds.
- */
- private final int DEFAULT_REFRESH_INTERVAL = 15;
-
- private ScheduledFuture<?> refreshJob;
+ private @Nullable ScheduledFuture<?> refreshJob;
private final Runnable refreshRunnable = new Runnable() {
};
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());
-
- if (upnpIOService != null) {
- this.service = upnpIOService;
- } else {
- logger.debug("upnpIOService not set.");
- }
}
@Override
public void dispose() {
logger.debug("WeMoMakerHandler disposed.");
- if (refreshJob != null && !refreshJob.isCancelled()) {
- refreshJob.cancel(true);
- refreshJob = null;
+ ScheduledFuture<?> job = refreshJob;
+ if (job != null && !job.isCancelled()) {
+ job.cancel(true);
}
+ refreshJob = null;
}
@Override
+ "<BinaryState>" + binaryState + "</BinaryState>" + "</u:SetBinaryState>" + "</s:Body>"
+ "</s:Envelope>";
- String wemoURL = getWemoURL("basicevent");
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, "basicevent");
if (wemoURL != null) {
- @SuppressWarnings("unused")
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ wemoCall.executeCall(wemoURL, soapHeader, content);
}
} catch (Exception e) {
logger.error("Failed to send command '{}' for device '{}' ", command, getThing().getUID(), e);
}
private synchronized void onUpdate() {
- if (service.isRegistered(this)) {
- if (refreshJob == null || refreshJob.isCancelled()) {
- Configuration config = getThing().getConfiguration();
- int refreshInterval = DEFAULT_REFRESH_INTERVAL;
- Object refreshConfig = config.get("refresh");
- if (refreshConfig != null) {
- refreshInterval = ((BigDecimal) refreshConfig).intValue();
- }
- refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
+ ScheduledFuture<?> job = refreshJob;
+ if (job == null || job.isCancelled()) {
+ Configuration config = getThing().getConfiguration();
+ int refreshInterval = DEFAULT_REFRESH_INTERVALL_SECONDS;
+ Object refreshConfig = config.get("refresh");
+ if (refreshConfig != null) {
+ refreshInterval = ((BigDecimal) refreshConfig).intValue();
}
+ refreshJob = scheduler.scheduleWithFixedDelay(refreshRunnable, 0, refreshInterval, TimeUnit.SECONDS);
}
}
/**
* The {@link updateWemoState} polls the actual state of a WeMo Maker.
*/
- @SuppressWarnings("null")
protected void updateWemoState() {
String action = "GetAttributes";
String actionService = "deviceevent";
+ action + ">" + "</s:Body>" + "</s:Envelope>";
try {
- String wemoURL = getWemoURL(actionService);
+ URL descriptorURL = service.getDescriptorURL(this);
+ String wemoURL = getWemoURL(descriptorURL, actionService);
+
if (wemoURL != null) {
- String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
+ String wemoCallResponse = wemoCall.executeCall(wemoURL, soapHeader, content);
if (wemoCallResponse != null) {
try {
- String stringParser = StringUtils.substringBetween(wemoCallResponse, "<attributeList>",
- "</attributeList>");
+ String stringParser = substringBetween(wemoCallResponse, "<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.
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
- stringParser = StringEscapeUtils.unescapeXml(stringParser);
-
+ stringParser = unescapeXml(stringParser);
+ stringParser = unescapeXml(stringParser);
logger.trace("Maker response '{}' for device '{}' received", stringParser, getThing().getUID());
stringParser = "<data>" + stringParser + "</data>";
switch (attributeName) {
case "Switch":
State relayState = attributeValue.equals("0") ? OnOffType.OFF : OnOffType.ON;
- if (relayState != null) {
- logger.debug("New relayState '{}' for device '{}' received", relayState,
- getThing().getUID());
- updateState(CHANNEL_RELAY, relayState);
- }
+ logger.debug("New relayState '{}' for device '{}' received", relayState,
+ getThing().getUID());
+ updateState(CHANNEL_RELAY, relayState);
break;
case "Sensor":
State sensorState = attributeValue.equals("1") ? OnOffType.OFF : OnOffType.ON;
- if (sensorState != null) {
- logger.debug("New sensorState '{}' for device '{}' received", sensorState,
- getThing().getUID());
- updateState(CHANNEL_SENSOR, sensorState);
- }
+ logger.debug("New sensorState '{}' for device '{}' received", sensorState,
+ getThing().getUID());
+ updateState(CHANNEL_SENSOR, sensorState);
break;
}
}
}
}
- 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) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
}
@Override
- public void onServiceSubscribed(String service, boolean succeeded) {
+ public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
}
@Override
- public void onValueReceived(String variable, String value, String service) {
+ public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
}
}
import java.nio.charset.StandardCharsets;
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.core.io.net.http.HttpUtil;
import org.slf4j.Logger;
*
* @author Hans-Jörg Merk - Initial contribution
*/
-
+@NonNullByDefault
public class WemoHttpCall {
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 {
Properties wemoHeaders = new Properties();
wemoHeaders.setProperty("CONTENT-TYPE", WemoBindingConstants.HTTP_CALL_CONTENT_HEADER);
public class WemoDiscoveryParticipantTest {
UpnpDiscoveryParticipant participant = new WemoDiscoveryParticipant();
- private final String DEVICE_UDN = GenericWemoOSGiTest.DEVICE_MANUFACTURER + "_3434xxx";
- private final String DEVICE_FRIENDLY_NAME = "Wemo Test";
+ private static final String DEVICE_UDN = GenericWemoOSGiTest.DEVICE_MANUFACTURER + "_3434xxx";
+ private static final String DEVICE_FRIENDLY_NAME = "Wemo Test";
RemoteDevice createUpnpDevice(String modelName)
throws MalformedURLException, ValidationException, URISyntaxException {
import org.junit.jupiter.api.Test;
import org.jupnp.model.ValidationException;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
import org.openhab.binding.wemo.internal.WemoBindingConstants;
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.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID;
public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
// Thing information
- private final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
- private final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
- private final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_SOCKET;
+ private static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
+ private static final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
+ private static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_SOCKET;
// UPnP information
- private final String MODEL_NAME = WemoBindingConstants.THING_TYPE_SOCKET.getId();
- private final String SERVICE_ID = "basicevent";
- private final String SERVICE_NUMBER = "1";
+ private static final String MODEL_NAME = WemoBindingConstants.THING_TYPE_SOCKET.getId();
+ private static final String SERVICE_ID = "basicevent";
+ private static final String SERVICE_NUMBER = "1";
@BeforeEach
public void setUp() throws IOException {
throws MalformedURLException, URISyntaxException, ValidationException {
Command command = OnOffType.OFF;
- WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
- Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
+ Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
waitForAssert(() -> {
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
throws MalformedURLException, URISyntaxException, ValidationException {
Command command = RefreshType.REFRESH;
- WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
- Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
+ Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
waitForAssert(() -> {
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
*/
public class WemoHandlerTest {
- private final ThingTypeUID THING_TYPE = WemoBindingConstants.THING_TYPE_INSIGHT;
- private final String THING_ID = "test";
+ private static final ThingTypeUID THING_TYPE = WemoBindingConstants.THING_TYPE_INSIGHT;
+ private static final String THING_ID = "test";
private MockWemoHandler handler;
- private final String SERVICE_ID = "insight";
- private final String PARAMS_NAME = "InsightParams";
+ private static final String SERVICE_ID = "insight";
+ private static final String PARAMS_NAME = "InsightParams";
private WemoInsightParams insightParams;
/** 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 **/
- private final int STATE_PARAM = 1;
+ private static final int STATE_PARAM = 1;
/** Represents power in Wats **/
- private final int POWER_PARAM = 54;
+ private static final int POWER_PARAM = 54;
private final Thing thing = mock(Thing.class);
import org.junit.jupiter.api.Test;
import org.jupnp.model.ValidationException;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
import org.openhab.binding.wemo.internal.WemoBindingConstants;
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.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
String capitability) throws MalformedURLException, URISyntaxException, ValidationException {
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, mockCaller);
+ Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
waitForAssert(() -> {
assertThat(bridge.getStatus(), is(ThingStatus.ONLINE));
import org.junit.jupiter.api.Test;
import org.jupnp.model.ValidationException;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
import org.openhab.binding.wemo.internal.WemoBindingConstants;
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.core.library.types.OnOffType;
import org.openhab.core.thing.ChannelUID;
public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
// Specific Thing information
- private final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_RELAY;
- private final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
- private final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MAKER;
+ private static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_RELAY;
+ private static final String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
+ private static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MAKER;
// Specific UpnP service information
- private final String MODEL = THING_TYPE_UID.getId();
- private final String BASIC_EVENT_SERVICE_ID = "basicevent";
- private final String SERVICE_NUMBER = "1";
+ private static final String MODEL = THING_TYPE_UID.getId();
+ private static final String BASIC_EVENT_SERVICE_ID = "basicevent";
+ private static final String SERVICE_NUMBER = "1";
@BeforeEach
public void setUp() throws IOException {
throws MalformedURLException, URISyntaxException, ValidationException {
Command command = OnOffType.OFF;
- WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
- Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
+ Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
waitForAssert(() -> {
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
throws MalformedURLException, URISyntaxException, ValidationException {
Command command = RefreshType.REFRESH;
- WemoHttpCall mockCaller = Mockito.spy(new WemoHttpCall());
- Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE, mockCaller);
+ Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
waitForAssert(() -> {
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
import org.openhab.binding.wemo.internal.WemoBindingConstants;
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.thing.Bridge;
import org.openhab.core.thing.Channel;
public class GenericWemoLightOSGiTestParent extends GenericWemoOSGiTest {
// Thing information
- protected ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MZ100;
- protected ThingTypeUID BRIDGE_TYPE_UID = WemoBindingConstants.THING_TYPE_BRIDGE;
- protected String WEMO_BRIDGE_ID = BRIDGE_TYPE_UID.getId();
- protected String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
- protected String DEFAULT_TEST_CHANNEL_TYPE = "Switch";
+ protected static final ThingTypeUID THING_TYPE_UID = WemoBindingConstants.THING_TYPE_MZ100;
+ protected static final ThingTypeUID BRIDGE_TYPE_UID = WemoBindingConstants.THING_TYPE_BRIDGE;
+ protected static final String WEMO_BRIDGE_ID = BRIDGE_TYPE_UID.getId();
+ protected static final String DEFAULT_TEST_CHANNEL = WemoBindingConstants.CHANNEL_STATE;
+ 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
- protected String DEVICE_MODEL_NAME = WEMO_LIGHT_ID;
- protected String SERVICE_ID = "bridge";
- protected String SERVICE_NUMBER = "1";
- protected String SERVLET_URL = DEVICE_CONTROL_PATH + SERVICE_ID + SERVICE_NUMBER;
+ protected static final String DEVICE_MODEL_NAME = WEMO_LIGHT_ID;
+ protected static final String SERVICE_ID = "bridge";
+ protected static final String SERVICE_NUMBER = "1";
+ protected static final String SERVLET_URL = DEVICE_CONTROL_PATH + SERVICE_ID + SERVICE_NUMBER;
private Bridge bridge;
}
@Override
- protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType,
- WemoHttpCall wemoHttpCaller) {
+ protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType) {
Configuration configuration = new Configuration();
configuration.put(WemoBindingConstants.DEVICE_ID, WEMO_LIGHT_ID);
ThingHandler handler = thing.getHandler();
if (handler != null) {
AbstractWemoHandler h = (AbstractWemoHandler) handler;
- h.setWemoHttpCaller(wemoHttpCaller);
}
return thing;
import org.jupnp.model.types.ServiceId;
import org.jupnp.model.types.ServiceType;
import org.jupnp.model.types.UDN;
+import org.mockito.Mockito;
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.core.config.core.Configuration;
import org.openhab.core.io.transport.upnp.UpnpIOService;
import org.openhab.core.thing.ThingRegistry;
import org.openhab.core.thing.ThingTypeUID;
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.ThingBuilder;
import org.openhab.core.thing.type.ChannelKind;
*/
public abstract class GenericWemoOSGiTest extends JavaOSGiTest {
- public static MockUpnpService mockUpnpService;
public static final String DEVICE_MANUFACTURER = "Belkin";
// 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
- protected String TEST_THING_ID = "TestThing";
+ protected static final String TEST_THING_ID = "TestThing";
// 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 final int DEVICE_VERSION = 1;
- private 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_TYPE = "Test";
+ private static final int DEVICE_VERSION = 1;
+ private static final String DEVICE_URL = "http://127.0.0.1:" + ORG_OSGI_SERVICE_HTTP_PORT;
+ private static final String DEVICE_DESCRIPTION_PATH = "/setup.xml";
- protected final String DEVICE_FRIENDLY_NAME = "WeMo Test";
- protected final String DEVICE_CONTROL_PATH = "/upnp/control/";
- protected final ChannelTypeUID DEFAULT_CHANNEL_TYPE_UID = new ChannelTypeUID(
+ protected static final String DEVICE_FRIENDLY_NAME = "WeMo Test";
+ protected static final String DEVICE_CONTROL_PATH = "/upnp/control/";
+ protected static final ChannelTypeUID DEFAULT_CHANNEL_TYPE_UID = new ChannelTypeUID(
WemoBindingConstants.BINDING_ID + ":channelType");
protected ManagedThingProvider managedThingProvider;
protected UpnpIOService upnpIOService;
protected ThingRegistry thingRegistry;
+ protected WemoHttpCall mockCaller;
+ protected MockUpnpService mockUpnpService;
+
protected Thing thing;
protected void setUpServices() throws IOException {
+ WemoUtil.serviceAvailableFunction = (host, port) -> true;
+
// StorageService is required from the ManagedThingProvider
VolatileStorageService volatileStorageService = new VolatileStorageService();
registerService(volatileStorageService);
upnpIOService = getService(UpnpIOService.class);
assertThat(upnpIOService, is(notNullValue()));
+ mockCaller = Mockito.spy(new WemoHttpCall());
+ WemoHttpCallFactory wemoHttpCallFactory = () -> mockCaller;
+ registerService(wemoHttpCallFactory, WemoHttpCallFactory.class.getName());
+
ChannelTypeProvider channelTypeProvider = mock(ChannelTypeProvider.class);
when(channelTypeProvider.getChannelType(any(ChannelTypeUID.class), any(Locale.class))).thenReturn(
ChannelTypeBuilder.state(DEFAULT_CHANNEL_TYPE_UID, "label", CoreItemFactory.SWITCH).build());
registerService(channelTypeProvider);
}
- protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType,
- WemoHttpCall wemoHttpCaller) {
+ protected Thing createThing(ThingTypeUID thingTypeUID, String channelID, String itemAcceptedType) {
Configuration configuration = new Configuration();
configuration.put(WemoBindingConstants.UDN, DEVICE_UDN);
.build();
managedThingProvider.add(thing);
-
- ThingHandler handler = thing.getHandler();
- if (handler != null) {
- AbstractWemoHandler h = (AbstractWemoHandler) handler;
- h.setWemoHttpCaller(wemoHttpCaller);
- }
-
return thing;
}
UDN udn = new UDN(DEVICE_UDN);
URL deviceURL = new URL(DEVICE_URL + DEVICE_DESCRIPTION_PATH);
- RemoteDeviceIdentity identity = new RemoteDeviceIdentity(udn, WemoBindingConstants.SUBSCRIPTION_DURATION,
- deviceURL, new byte[1], null);
+ RemoteDeviceIdentity identity = new RemoteDeviceIdentity(udn,
+ WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS, deviceURL, new byte[1], null);
DeviceType type = new DeviceType(DEVICE_MANUFACTURER, DEVICE_TYPE, DEVICE_VERSION);
ManufacturerDetails manufacturerDetails = new ManufacturerDetails(DEVICE_MANUFACTURER);