[wemo] Improve GENA subscription reliability and error handling (#12148)
* Consolidate service subscriptions in base class. * Remove unsynchronized and unneeded cache of subscriptions. * Do not unregister participant when removing subscription. * Fix status wrongly set to ONLINE when exception is thrown. * Refactor error handling for WemoHttpCall. * Adjust log level for communication errors. * Add automatic subscription renewal. * Fix more ONLINE/OFFLINE status transition issues. * Adjust log level when getWemoURL fails because device is offline. * Remove redundant logging. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
parent
882e52647d
commit
8ebd4e9047
|
@ -133,7 +133,6 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
|||
|
||||
String endDeviceRequest = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
|
||||
if (endDeviceRequest != null) {
|
||||
logger.trace("endDeviceRequest answered '{}'", endDeviceRequest);
|
||||
|
||||
try {
|
||||
|
@ -207,9 +206,8 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
|||
properties.put(DEVICE_ID, endDeviceID);
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID)
|
||||
.withProperties(properties)
|
||||
.withBridge(wemoBridgeHandler.getThing().getUID()).withLabel(endDeviceName)
|
||||
.build();
|
||||
.withProperties(properties).withBridge(wemoBridgeHandler.getThing().getUID())
|
||||
.withLabel(endDeviceName).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
|
@ -224,13 +222,11 @@ public class WemoLinkDiscoveryService extends AbstractDiscoveryService implement
|
|||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to parse endDevices for bridge '{}'",
|
||||
wemoBridgeHandler.getThing().getUID(), e);
|
||||
}
|
||||
logger.warn("Failed to parse endDevices for bridge '{}'", wemoBridgeHandler.getThing().getUID(), e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get endDevices for bridge '{}'", wemoBridgeHandler.getThing().getUID(), e);
|
||||
logger.warn("Failed to get endDevices for bridge '{}'", wemoBridgeHandler.getThing().getUID(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
package org.openhab.binding.wemo.internal.handler;
|
||||
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
@ -24,20 +29,30 @@ import org.openhab.core.thing.ChannelUID;
|
|||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link WemoBaseThingHandler} provides a base implementation for the
|
||||
* concrete WeMo handlers for each thing type.
|
||||
* concrete WeMo handlers.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class WemoBaseThingHandler extends BaseThingHandler implements UpnpIOParticipant {
|
||||
|
||||
private static final int SUBSCRIPTION_RENEWAL_INITIAL_DELAY_SECONDS = 15;
|
||||
private static final int SUBSCRIPTION_RENEWAL_INTERVAL_SECONDS = 60;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WemoBaseThingHandler.class);
|
||||
|
||||
protected @Nullable UpnpIOService service;
|
||||
protected WemoHttpCall wemoHttpCaller;
|
||||
protected String host = "";
|
||||
|
||||
private Map<String, Instant> subscriptions = new ConcurrentHashMap<String, Instant>();
|
||||
private @Nullable ScheduledFuture<?> subscriptionRenewalJob;
|
||||
|
||||
public WemoBaseThingHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||
super(thing);
|
||||
this.service = upnpIOService;
|
||||
|
@ -46,7 +61,22 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// can be overridden by subclasses
|
||||
UpnpIOService service = this.service;
|
||||
if (service != null) {
|
||||
logger.debug("Registering UPnP participant for {}", getThing().getUID());
|
||||
service.registerParticipant(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
removeSubscriptions();
|
||||
UpnpIOService service = this.service;
|
||||
if (service != null) {
|
||||
logger.debug("Unregistering UPnP participant for {}", getThing().getUID());
|
||||
service.unregisterParticipant(this);
|
||||
}
|
||||
cancelSubscriptionRenewalJob();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +96,13 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
|
|||
|
||||
@Override
|
||||
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||
// can be overridden by subclasses
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
logger.debug("Subscription to service {} for {} {}", service, getUDN(), succeeded ? "succeeded" : "failed");
|
||||
if (succeeded) {
|
||||
subscriptions.put(service, Instant.now());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,10 +112,115 @@ public abstract class WemoBaseThingHandler extends BaseThingHandler implements U
|
|||
|
||||
protected boolean isUpnpDeviceRegistered() {
|
||||
UpnpIOService service = this.service;
|
||||
if (service != null) {
|
||||
return service.isRegistered(this);
|
||||
return service != null && service.isRegistered(this);
|
||||
}
|
||||
return false;
|
||||
|
||||
protected void addSubscription(String serviceId) {
|
||||
if (subscriptions.containsKey(serviceId)) {
|
||||
logger.debug("{} already subscribed to {}", getUDN(), serviceId);
|
||||
return;
|
||||
}
|
||||
if (subscriptions.isEmpty()) {
|
||||
logger.debug("Adding first GENA subscription for {}, scheduling renewal job", getUDN());
|
||||
scheduleSubscriptionRenewalJob();
|
||||
}
|
||||
subscriptions.put(serviceId, Instant.ofEpochSecond(0));
|
||||
UpnpIOService service = this.service;
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
logger.debug("Registering UPnP participant for {}", getUDN());
|
||||
service.registerParticipant(this);
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
logger.debug("Trying to add GENA subscription {} for {}, but service is not registered", serviceId,
|
||||
getUDN());
|
||||
return;
|
||||
}
|
||||
logger.debug("Adding GENA subscription {} for {}", serviceId, getUDN());
|
||||
service.addSubscription(this, serviceId, WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS);
|
||||
}
|
||||
|
||||
protected void removeSubscription(String serviceId) {
|
||||
UpnpIOService service = this.service;
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
subscriptions.remove(serviceId);
|
||||
if (subscriptions.isEmpty()) {
|
||||
logger.debug("Removing last GENA subscription for {}, cancelling renewal job", getUDN());
|
||||
cancelSubscriptionRenewalJob();
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
logger.debug("Trying to remove GENA subscription {} for {}, but service is not registered", serviceId,
|
||||
getUDN());
|
||||
return;
|
||||
}
|
||||
logger.debug("Unsubscribing {} from service {}", getUDN(), serviceId);
|
||||
service.removeSubscription(this, serviceId);
|
||||
}
|
||||
|
||||
private void scheduleSubscriptionRenewalJob() {
|
||||
cancelSubscriptionRenewalJob();
|
||||
this.subscriptionRenewalJob = scheduler.scheduleWithFixedDelay(this::renewSubscriptions,
|
||||
SUBSCRIPTION_RENEWAL_INITIAL_DELAY_SECONDS, SUBSCRIPTION_RENEWAL_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void cancelSubscriptionRenewalJob() {
|
||||
ScheduledFuture<?> subscriptionRenewalJob = this.subscriptionRenewalJob;
|
||||
if (subscriptionRenewalJob != null) {
|
||||
subscriptionRenewalJob.cancel(true);
|
||||
}
|
||||
this.subscriptionRenewalJob = null;
|
||||
}
|
||||
|
||||
private void renewSubscriptions() {
|
||||
if (subscriptions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
UpnpIOService service = this.service;
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
service.registerParticipant(this);
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
logger.debug("Trying to renew GENA subscriptions for {}, but service is not registered", getUDN());
|
||||
return;
|
||||
}
|
||||
logger.debug("Renewing GENA subscriptions for {}", getUDN());
|
||||
subscriptions.forEach((serviceId, lastRenewed) -> {
|
||||
if (lastRenewed.isBefore(Instant.now().minusSeconds(
|
||||
WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS - SUBSCRIPTION_RENEWAL_INTERVAL_SECONDS))) {
|
||||
logger.debug("Subscription for service {} with timestamp {} has expired, renewing", serviceId,
|
||||
lastRenewed);
|
||||
service.removeSubscription(this, serviceId);
|
||||
service.addSubscription(this, serviceId, WemoBindingConstants.SUBSCRIPTION_DURATION_SECONDS);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeSubscriptions() {
|
||||
if (subscriptions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
UpnpIOService service = this.service;
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
if (!service.isRegistered(this)) {
|
||||
logger.debug("Trying to remove GENA subscriptions for {}, but service is not registered",
|
||||
getThing().getUID());
|
||||
return;
|
||||
}
|
||||
logger.debug("Removing GENA subscriptions for {}", getUDN());
|
||||
subscriptions.forEach((serviceId, lastRenewed) -> {
|
||||
logger.debug("Removing subscription for service {}", serviceId);
|
||||
service.removeSubscription(this, serviceId);
|
||||
});
|
||||
subscriptions.clear();
|
||||
}
|
||||
|
||||
protected String getHost() {
|
||||
|
|
|
@ -19,8 +19,6 @@ import java.io.StringReader;
|
|||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
@ -67,11 +65,8 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_COFFEE);
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
public WemoCoffeeHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||
|
@ -82,14 +77,12 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoCoffeeHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
addSubscription(DEVICEEVENT);
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
@ -103,13 +96,13 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("WeMoCoffeeHandler disposed.");
|
||||
logger.debug("WemoCoffeeHandler disposed.");
|
||||
ScheduledFuture<?> job = this.pollingJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -127,14 +120,9 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -145,7 +133,7 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -153,7 +141,7 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -184,97 +172,35 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
+ "<attribute><name>Cleaning</name><value>NULL</value></attribute></attributeList>"
|
||||
+ "</u:SetAttributes>" + "</s:Body>" + "</s:Envelope>";
|
||||
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateState(CHANNEL_STATE, OnOffType.ON);
|
||||
State newMode = new StringType("Brewing");
|
||||
updateState(CHANNEL_COFFEEMODE, newMode);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader,
|
||||
getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content,
|
||||
getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse,
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||
logger.warn("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||
e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
// if command.equals(OnOffType.OFF) we do nothing because WeMo Coffee Maker cannot be switched
|
||||
// off
|
||||
// remotely
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
// off remotely
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||
// We can subscribe to GENA events, but there is no usefull response right now.
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
String subscription = DEVICEEVENT;
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
"Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
String subscription = DEVICEEVENT;
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
subscriptionState = new HashMap<>();
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link updateWemoState} polls the actual state of a WeMo CoffeeMaker.
|
||||
*/
|
||||
protected void updateWemoState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -282,7 +208,7 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
String actionService = DEVICEACTION;
|
||||
String wemoURL = getWemoURL(host, actionService);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -292,13 +218,6 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
String soapHeader = "\"urn:Belkin:service:" + actionService + ":1#" + action + "\"";
|
||||
String content = createStateRequestContent(action, actionService);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
try {
|
||||
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||
|
||||
|
@ -306,8 +225,7 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
stringParser = unescapeXml(stringParser);
|
||||
stringParser = unescapeXml(stringParser);
|
||||
|
||||
logger.trace("CoffeeMaker response '{}' for device '{}' received", stringParser,
|
||||
getThing().getUID());
|
||||
logger.trace("CoffeeMaker response '{}' for device '{}' received", stringParser, getThing().getUID());
|
||||
|
||||
stringParser = "<data>" + stringParser + "</data>";
|
||||
|
||||
|
@ -427,12 +345,13 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
break;
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to parse attributeList for WeMo CoffeMaker '{}'", this.getThing().getUID(), e);
|
||||
}
|
||||
logger.warn("Failed to parse attributeList for WeMo CoffeMaker '{}'", this.getThing().getUID(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get attributes for device '{}'", getThing().getUID(), e);
|
||||
logger.warn("Failed to get attributes for device '{}'", getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +360,7 @@ public class WemoCoffeeHandler extends WemoBaseThingHandler {
|
|||
try {
|
||||
value = Long.parseLong(attributeValue);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||
logger.warn("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||
getThing().getUID());
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ 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.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -53,13 +54,10 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_CROCKPOT);
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
public WemoCrockpotHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||
|
@ -70,14 +68,12 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoCrockpotHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
addSubscription(BASICEVENT);
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
@ -97,7 +93,7 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -114,14 +110,9 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -132,7 +123,7 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -140,7 +131,7 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -175,27 +166,12 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
+ "<s:Body>" + "<u:SetCrockpotState xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<mode>"
|
||||
+ mode + "</mode>" + "<time>" + time + "</time>" + "</u:SetCrockpotState>" + "</s:Body>"
|
||||
+ "</s:Envelope>";
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,49 +186,6 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
"Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
subscriptionState.remove(subscription);
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link updateWemoState} polls the actual state of a WeMo device and
|
||||
* calls {@link onValueReceived} to update the statemap and channels..
|
||||
|
@ -261,7 +194,7 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
protected void updateWemoState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -269,7 +202,7 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
String actionService = BASICEVENT;
|
||||
String wemoURL = getWemoURL(localHost, actionService);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -279,13 +212,6 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
String soapHeader = "\"urn:Belkin:service:" + actionService + ":1#" + action + "\"";
|
||||
String content = createStateRequestContent(action, actionService);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
String mode = substringBetween(wemoCallResponse, "<mode>", "</mode>");
|
||||
String time = substringBetween(wemoCallResponse, "<time>", "</time>");
|
||||
String coockedTime = substringBetween(wemoCallResponse, "<coockedTime>", "</coockedTime>");
|
||||
|
@ -314,11 +240,10 @@ public class WemoCrockpotHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
updateState(CHANNEL_COOKMODE, newMode);
|
||||
updateState(CHANNEL_COOKEDTIME, newCoockedTime);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to get actual state for device '{}': {}", getThing().getUID(), e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,13 +59,10 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DIMMER);
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
private int currentBrightness;
|
||||
|
@ -84,14 +81,12 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoDimmerHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
addSubscription(BASICEVENT);
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
@ -112,7 +107,7 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -129,14 +124,9 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -333,15 +323,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||
logger.debug("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
||||
|
@ -431,41 +412,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
String subscription = BASICEVENT;
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
String subscription = BASICEVENT;
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
subscriptionState = new HashMap<>();
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link updateWemoState} polls the actual state of a WeMo device and
|
||||
* calls {@link onValueReceived} to update the statemap and channels..
|
||||
|
@ -474,14 +420,14 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
protected void updateWemoState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -494,13 +440,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
String content = createStateRequestContent(action, actionService);
|
||||
try {
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
value = substringBetween(wemoCallResponse, "<BinaryState>", "</BinaryState>");
|
||||
variable = "BinaryState";
|
||||
this.onValueReceived(variable, value, actionService + "1");
|
||||
|
@ -511,7 +450,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
variable = "fader";
|
||||
this.onValueReceived(variable, value, actionService + "1");
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to get actual state for device '{}': {}", getThing().getUID(), e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
|
@ -523,13 +461,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
content = createStateRequestContent(action, actionService);
|
||||
try {
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
value = substringBetween(wemoCallResponse, "<startTime>", "</startTime>");
|
||||
variable = "startTime";
|
||||
this.onValueReceived(variable, value, actionService + "1");
|
||||
|
@ -543,8 +474,6 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
variable = "nightModeBrightness";
|
||||
this.onValueReceived(variable, value, actionService + "1");
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to get actual NightMode state for device '{}': {}", getThing().getUID(),
|
||||
e.getMessage());
|
||||
|
@ -557,27 +486,26 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
try {
|
||||
value = Long.parseLong(attributeValue);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.error("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||
logger.warn("Unable to parse attributeValue '{}' for device '{}'; expected long", attributeValue,
|
||||
getThing().getUID());
|
||||
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) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to set binary state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to set binary state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to set binary state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to set binary state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -589,13 +517,8 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
+ "<s:Body>" + "<u:" + action + " xmlns:u=\"urn:Belkin:service:basicevent:1\">" + "<" + argument
|
||||
+ ">" + value + "</" + argument + ">" + "</u:" + action + ">" + "</s:Body>" + "</s:Envelope>";
|
||||
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to set binaryState '{}' for device '{}': {}", value, getThing().getUID(),
|
||||
e.getMessage());
|
||||
|
@ -606,14 +529,14 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
public void setTimerStart(String action, String argument, String value) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to set timerStart for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to set timerStart for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to set timerStart for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.warn("Failed to set timerStart for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -624,13 +547,8 @@ public class WemoDimmerHandler extends WemoBaseThingHandler {
|
|||
+ "<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 wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed to set timerStart '{}' for device '{}': {}", value, getThing().getUID(),
|
||||
e.getMessage());
|
||||
|
|
|
@ -15,8 +15,6 @@ 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.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -30,7 +28,6 @@ import org.openhab.core.thing.ChannelUID;
|
|||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -51,11 +48,8 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(WemoHandler.class);
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
public WemoHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||
|
@ -66,13 +60,14 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
addSubscription(BASICEVENT);
|
||||
if (THING_TYPE_INSIGHT.equals(thing.getThingTypeUID())) {
|
||||
addSubscription(INSIGHTEVENT);
|
||||
}
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
|
@ -94,7 +89,7 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -111,14 +106,9 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -129,7 +119,7 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -137,7 +127,7 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -155,92 +145,13 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
boolean binaryState = OnOffType.ON.equals(command) ? true : false;
|
||||
String soapHeader = "\"urn:Belkin:service:basicevent:1#SetBinaryState\"";
|
||||
String content = createBinaryStateContent(binaryState);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse,
|
||||
getThing().getUID());
|
||||
}
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||
logger.warn("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||
e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
|
||||
if (THING_TYPE_INSIGHT.equals(thingTypeUID)) {
|
||||
subscription = INSIGHTEVENT;
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
"Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
|
||||
if (THING_TYPE_INSIGHT.equals(thingTypeUID)) {
|
||||
subscription = INSIGHTEVENT;
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
}
|
||||
subscriptionState = new HashMap<>();
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +165,7 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
String actionService = BASICACTION;
|
||||
String localhost = getHost();
|
||||
if (localhost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -269,7 +180,7 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localhost, actionService);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -278,13 +189,6 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
String content = createStateRequestContent(action, actionService);
|
||||
try {
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
if ("InsightParams".equals(variable)) {
|
||||
value = substringBetween(wemoCallResponse, "<InsightParams>", "</InsightParams>");
|
||||
} else {
|
||||
|
@ -294,9 +198,8 @@ public abstract class WemoHandler extends WemoBaseThingHandler {
|
|||
logger.trace("New state '{}' for device '{}' received", value, getThing().getUID());
|
||||
this.onValueReceived(variable, value, actionService + "1");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get actual state for device '{}': {}", getThing().getUID(), e.getMessage());
|
||||
logger.warn("Failed to get actual state for device '{}': {}", getThing().getUID(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,13 +68,10 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
private static final int FILTER_LIFE_DAYS = 330;
|
||||
private static final int FILTER_LIFE_MINS = FILTER_LIFE_DAYS * 24 * 60;
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private final Map<String, String> stateMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
public WemoHolmesHandler(Thing thing, UpnpIOService upnpIOService, WemoHttpCall wemoHttpCaller) {
|
||||
|
@ -85,14 +82,12 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoHolmesHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
addSubscription(BASICEVENT);
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
@ -113,7 +108,7 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -130,14 +125,9 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -148,7 +138,7 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -156,7 +146,7 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, DEVICEACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -269,27 +259,12 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
+ "<attributeList><attribute><name>" + attribute + "</name><value>" + value
|
||||
+ "</value></attribute></attributeList>" + "</u:SetAttributes>" + "</s:Body>"
|
||||
+ "</s:Envelope>";
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (IOException e) {
|
||||
logger.debug("Failed to send command '{}' for device '{}':", command, getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
|
@ -303,49 +278,6 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
subscription);
|
||||
localService.addSubscription(this, subscription, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(subscription, true);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
"Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
String subscription = BASICEVENT;
|
||||
|
||||
if (subscriptionState.get(subscription) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), subscription);
|
||||
localService.removeSubscription(this, subscription);
|
||||
}
|
||||
subscriptionState.remove(subscription);
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link updateWemoState} polls the actual state of a WeMo device and
|
||||
* calls {@link onValueReceived} to update the statemap and channels..
|
||||
|
@ -354,7 +286,7 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
protected void updateWemoState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -362,7 +294,7 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
String actionService = DEVICEACTION;
|
||||
String wemoURL = getWemoURL(localHost, actionService);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -372,14 +304,6 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
String soapHeader = "\"urn:Belkin:service:" + actionService + ":1#" + action + "\"";
|
||||
String content = createStateRequestContent(action, actionService);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
|
||||
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||
|
||||
// Due to Belkins bad response formatting, we need to run this twice.
|
||||
|
@ -580,11 +504,10 @@ public class WemoHolmesHandler extends WemoBaseThingHandler {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (RuntimeException | ParserConfigurationException | SAXException | IOException e) {
|
||||
logger.debug("Failed to get actual state for device '{}':", getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public class WemoInsightHandler extends WemoHandler {
|
|||
try {
|
||||
lastChangedAt = Long.parseLong(splitInsightParams[1]) * 1000; // convert s to ms
|
||||
} catch (NumberFormatException e) {
|
||||
logger.error("Unable to parse lastChangedAt value '{}' for device '{}'; expected long",
|
||||
logger.warn("Unable to parse lastChangedAt value '{}' for device '{}'; expected long",
|
||||
splitInsightParams[1], getThing().getUID());
|
||||
}
|
||||
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(lastChangedAt),
|
||||
|
|
|
@ -15,8 +15,6 @@ 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.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -52,9 +50,6 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(WemoLightHandler.class);
|
||||
|
||||
private Map<String, Boolean> subscriptionState = new HashMap<>();
|
||||
|
||||
private final Object upnpLock = new Object();
|
||||
private final Object jobLock = new Object();
|
||||
|
||||
private @Nullable WemoBridgeHandler wemoBridgeHandler;
|
||||
|
@ -68,8 +63,6 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
*/
|
||||
private static final int DIM_STEPSIZE = 5;
|
||||
|
||||
protected static final String SUBSCRIPTION = "bridge1";
|
||||
|
||||
/**
|
||||
* The default refresh initial delay in Seconds.
|
||||
*/
|
||||
|
@ -85,15 +78,13 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
// initialize() is only called if the required parameter 'deviceID' is available
|
||||
wemoLightID = (String) getConfig().get(DEVICE_ID);
|
||||
|
||||
final Bridge bridge = getBridge();
|
||||
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
addSubscription(BRIDGEEVENT);
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, DEFAULT_REFRESH_INITIAL_DELAY,
|
||||
DEFAULT_REFRESH_INTERVAL_SECONDS, TimeUnit.SECONDS);
|
||||
|
@ -119,20 +110,20 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("WeMoLightHandler disposed.");
|
||||
logger.debug("WemoLightHandler disposed.");
|
||||
|
||||
ScheduledFuture<?> job = this.pollingJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
removeSubscription();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private synchronized @Nullable WemoBridgeHandler getWemoBridgeHandler() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
logger.error("Required bridge not defined for device {}.", wemoLightID);
|
||||
logger.warn("Required bridge not defined for device {}.", wemoLightID);
|
||||
return null;
|
||||
}
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
@ -159,14 +150,9 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
logger.debug("UPnP device {} not yet registered", getUDN());
|
||||
updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
synchronized (upnpLock) {
|
||||
subscriptionState = new HashMap<>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
getDeviceState();
|
||||
addSubscription();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
}
|
||||
|
@ -177,7 +163,7 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -185,7 +171,7 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -277,25 +263,18 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
+ "</CapabilityValue></DeviceStatus>" + "</DeviceStatusList>"
|
||||
+ "</u:SetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
||||
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader,
|
||||
getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse,
|
||||
getThing().getUID());
|
||||
}
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if ("10008".equals(capability)) {
|
||||
OnOffType binaryState = null;
|
||||
binaryState = "0".equals(value) ? OnOffType.OFF : OnOffType.ON;
|
||||
updateState(CHANNEL_STATE, binaryState);
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Could not send command to WeMo Bridge", e);
|
||||
logger.warn("Failed to send command '{}' for device '{}': {}", command, getThing().getUID(),
|
||||
e.getMessage());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +296,7 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
public void getDeviceState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -325,7 +304,7 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
logger.debug("Request actual state for LightID '{}'", wemoLightID);
|
||||
String wemoURL = getWemoURL(localHost, BRIDGEACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -338,13 +317,6 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
+ wemoLightID + "</DeviceIDs>" + "</u:GetDeviceStatus>" + "</s:Body>" + "</s:Envelope>";
|
||||
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
wemoCallResponse = unescapeXml(wemoCallResponse);
|
||||
String response = substringBetween(wemoCallResponse, "<CapabilityValue>", "</CapabilityValue>");
|
||||
logger.trace("wemoNewLightState = {}", response);
|
||||
|
@ -365,16 +337,13 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
currentBrightness = newBrightness;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Could not retrieve new Wemo light state", e);
|
||||
logger.debug("Could not retrieve new Wemo light state for '{}':", getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceSubscribed(@Nullable String service, boolean succeeded) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueReceived(@Nullable String variable, @Nullable String value, @Nullable String service) {
|
||||
logger.trace("Received pair '{}':'{}' (service '{}') for thing '{}'",
|
||||
|
@ -399,44 +368,4 @@ public class WemoLightHandler extends WemoBaseThingHandler {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Checking WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
if (subscriptionState.get(SUBSCRIPTION) == null) {
|
||||
logger.debug("Setting up GENA subscription {}: Subscribing to service {}...", getUDN(),
|
||||
SUBSCRIPTION);
|
||||
localService.addSubscription(this, SUBSCRIPTION, SUBSCRIPTION_DURATION_SECONDS);
|
||||
subscriptionState.put(SUBSCRIPTION, true);
|
||||
}
|
||||
} else {
|
||||
logger.debug(
|
||||
"Setting up WeMo GENA subscription for '{}' FAILED - service.isRegistered(this) is FALSE",
|
||||
getThing().getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeSubscription() {
|
||||
synchronized (upnpLock) {
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
if (localService.isRegistered(this)) {
|
||||
logger.debug("Removing WeMo GENA subscription for '{}'", getThing().getUID());
|
||||
|
||||
if (subscriptionState.get(SUBSCRIPTION) != null) {
|
||||
logger.debug("WeMo {}: Unsubscribing from service {}...", getUDN(), SUBSCRIPTION);
|
||||
localService.removeSubscription(this, SUBSCRIPTION);
|
||||
}
|
||||
subscriptionState = new HashMap<>();
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,14 +70,11 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
Configuration configuration = getConfig();
|
||||
|
||||
if (configuration.get(UDN) != null) {
|
||||
logger.debug("Initializing WemoMakerHandler for UDN '{}'", configuration.get(UDN));
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.registerParticipant(this);
|
||||
}
|
||||
host = getHost();
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, DEFAULT_REFRESH_INTERVAL_SECONDS,
|
||||
TimeUnit.SECONDS);
|
||||
|
@ -91,17 +88,14 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("WeMoMakerHandler disposed.");
|
||||
logger.debug("WemoMakerHandler disposed.");
|
||||
|
||||
ScheduledFuture<?> job = this.pollingJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
job.cancel(true);
|
||||
}
|
||||
this.pollingJob = null;
|
||||
UpnpIOService localService = service;
|
||||
if (localService != null) {
|
||||
localService.unregisterParticipant(this);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
|
@ -120,7 +114,6 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
"@text/config-status.pending.device-not-registered [\"" + getUDN() + "\"]");
|
||||
return;
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateWemoState();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception during poll: {}", e.getMessage(), e);
|
||||
|
@ -132,7 +125,7 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
logger.warn("Failed to send command '{}' for device '{}': IP address missing", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
|
@ -140,7 +133,7 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
}
|
||||
String wemoURL = getWemoURL(localHost, BASICACTION);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
logger.debug("Failed to send command '{}' for device '{}': URL cannot be created", command,
|
||||
getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
|
@ -158,16 +151,11 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
boolean binaryState = OnOffType.ON.equals(command) ? true : false;
|
||||
String soapHeader = "\"urn:Belkin:service:basicevent:1#SetBinaryState\"";
|
||||
String content = createBinaryStateContent(binaryState);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null && logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse,
|
||||
getThing().getUID());
|
||||
}
|
||||
wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to send command '{}' for device '{}' ", command, getThing().getUID(), e);
|
||||
logger.warn("Failed to send command '{}' for device '{}' ", command, getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +167,7 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
protected void updateWemoState() {
|
||||
String localHost = getHost();
|
||||
if (localHost.isEmpty()) {
|
||||
logger.error("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
logger.warn("Failed to get actual state for device '{}': IP address missing", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-ip");
|
||||
return;
|
||||
|
@ -187,7 +175,7 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
String actionService = DEVICEACTION;
|
||||
String wemoURL = getWemoURL(localHost, actionService);
|
||||
if (wemoURL == null) {
|
||||
logger.error("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
logger.debug("Failed to get actual state for device '{}': URL cannot be created", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"@text/config-status.error.missing-url");
|
||||
return;
|
||||
|
@ -197,13 +185,6 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
String soapHeader = "\"urn:Belkin:service:" + actionService + ":1#" + action + "\"";
|
||||
String content = createStateRequestContent(action, actionService);
|
||||
String wemoCallResponse = wemoHttpCaller.executeCall(wemoURL, soapHeader, content);
|
||||
if (wemoCallResponse != null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("wemoCall to URL '{}' for device '{}'", wemoURL, getThing().getUID());
|
||||
logger.trace("wemoCall with soapHeader '{}' for device '{}'", soapHeader, getThing().getUID());
|
||||
logger.trace("wemoCall with content '{}' for device '{}'", content, getThing().getUID());
|
||||
logger.trace("wemoCall with response '{}' for device '{}'", wemoCallResponse, getThing().getUID());
|
||||
}
|
||||
try {
|
||||
String stringParser = substringBetween(wemoCallResponse, "<attributeList>", "</attributeList>");
|
||||
logger.trace("Escaped Maker response for device '{}' :", getThing().getUID());
|
||||
|
@ -260,12 +241,13 @@ public class WemoMakerHandler extends WemoBaseThingHandler {
|
|||
break;
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to parse attributeList for WeMo Maker '{}'", this.getThing().getUID(), e);
|
||||
}
|
||||
logger.warn("Failed to parse attributeList for WeMo Maker '{}'", this.getThing().getUID(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to get attributes for device '{}'", getThing().getUID(), e);
|
||||
logger.warn("Failed to get attributes for device '{}'", getThing().getUID(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ 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;
|
||||
|
@ -35,20 +34,18 @@ public class WemoHttpCall {
|
|||
|
||||
private final Logger logger = LoggerFactory.getLogger(WemoHttpCall.class);
|
||||
|
||||
public @Nullable String executeCall(String wemoURL, String soapHeader, String content) {
|
||||
try {
|
||||
public String executeCall(String wemoURL, String soapHeader, String content) throws IOException {
|
||||
Properties wemoHeaders = new Properties();
|
||||
wemoHeaders.setProperty("CONTENT-TYPE", WemoBindingConstants.HTTP_CALL_CONTENT_HEADER);
|
||||
wemoHeaders.put("SOAPACTION", soapHeader);
|
||||
|
||||
InputStream wemoContent = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
String wemoCallResponse = HttpUtil.executeUrl("POST", wemoURL, wemoHeaders, wemoContent, null, 2000);
|
||||
return wemoCallResponse;
|
||||
} catch (IOException e) {
|
||||
// throw new IllegalStateException("Could not call WeMo", e);
|
||||
logger.debug("Could not make HTTP call to WeMo");
|
||||
return null;
|
||||
}
|
||||
logger.trace("Performing HTTP call for URL: '{}', header: '{}', request body: '{}'", wemoURL, soapHeader,
|
||||
content);
|
||||
String responseBody = HttpUtil.executeUrl("POST", wemoURL, wemoHeaders, wemoContent, null, 2000);
|
||||
logger.trace("HTTP response body: '{}'", responseBody);
|
||||
|
||||
return responseBody;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public class WemoLinkDiscoveryServiceOSGiTest extends GenericWemoLightOSGiTestPa
|
|||
|
||||
@Test
|
||||
public void assertSupportedThingIsDiscovered()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
String model = WemoBindingConstants.THING_TYPE_MZ100.getId();
|
||||
addUpnpDevice(SERVICE_ID, SERVICE_NUMBER, model);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
|||
|
||||
@Test
|
||||
public void assertThatThingHandlesOnOffCommandCorrectly()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = OnOffType.OFF;
|
||||
|
||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||
|
@ -105,7 +105,7 @@ public class WemoHandlerOSGiTest extends GenericWemoOSGiTest {
|
|||
|
||||
@Test
|
||||
public void assertThatThingHandlesREFRESHCommandCorrectly()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = RefreshType.REFRESH;
|
||||
|
||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||
|
|
|
@ -65,7 +65,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
|
||||
@Test
|
||||
public void handleONcommandForBRIGHTNESSchannel()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = OnOffType.ON;
|
||||
String channelID = WemoBindingConstants.CHANNEL_BRIGHTNESS;
|
||||
|
||||
|
@ -80,7 +80,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
|
||||
@Test
|
||||
public void handlePercentCommandForBRIGHTNESSChannel()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
// Set brightness value to 20 Percent
|
||||
Command command = new PercentType(20);
|
||||
String channelID = WemoBindingConstants.CHANNEL_BRIGHTNESS;
|
||||
|
@ -95,7 +95,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
|
||||
@Test
|
||||
public void handleIncreaseCommandForBRIGHTNESSchannel()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
// The value is increased by 5 Percents by default
|
||||
Command command = IncreaseDecreaseType.INCREASE;
|
||||
String channelID = WemoBindingConstants.CHANNEL_BRIGHTNESS;
|
||||
|
@ -110,7 +110,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
|
||||
@Test
|
||||
public void handleDecreaseCommandForBRIGHTNESSchannel()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
// The value can not be decreased below 0
|
||||
Command command = IncreaseDecreaseType.DECREASE;
|
||||
String channelID = WemoBindingConstants.CHANNEL_BRIGHTNESS;
|
||||
|
@ -123,7 +123,8 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void handleOnCommandForSTATEChannel() throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
public void handleOnCommandForSTATEChannel()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = OnOffType.ON;
|
||||
String channelID = WemoBindingConstants.CHANNEL_STATE;
|
||||
|
||||
|
@ -137,7 +138,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
|
||||
@Test
|
||||
public void handleREFRESHCommandForChannelSTATE()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = RefreshType.REFRESH;
|
||||
String channelID = WemoBindingConstants.CHANNEL_STATE;
|
||||
|
||||
|
@ -149,7 +150,7 @@ public class WemoLightHandlerOSGiTest extends GenericWemoLightOSGiTestParent {
|
|||
}
|
||||
|
||||
private void assertRequestForCommand(String channelID, Command command, String action, String value,
|
||||
String capitability) throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
String capitability) throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Thing bridge = createBridge(BRIDGE_TYPE_UID);
|
||||
|
||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||
|
|
|
@ -70,7 +70,7 @@ public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
|||
|
||||
@Test
|
||||
public void assertThatThingHandlesOnOffCommandCorrectly()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = OnOffType.OFF;
|
||||
|
||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||
|
@ -106,7 +106,7 @@ public class WemoMakerHandlerOSGiTest extends GenericWemoOSGiTest {
|
|||
|
||||
@Test
|
||||
public void assertThatThingHandlesREFRESHCommand()
|
||||
throws MalformedURLException, URISyntaxException, ValidationException {
|
||||
throws MalformedURLException, URISyntaxException, ValidationException, IOException {
|
||||
Command command = RefreshType.REFRESH;
|
||||
|
||||
Thing thing = createThing(THING_TYPE_UID, DEFAULT_TEST_CHANNEL, DEFAULT_TEST_CHANNEL_TYPE);
|
||||
|
|
Loading…
Reference in New Issue