[tapocontrol] fixed configuration error (#13677)

* improved response logging and error handling

Signed-off-by: Christian Wild <christian@wildclan.de>
This commit is contained in:
Christian Wild 2022-11-14 10:13:05 +01:00 committed by GitHub
parent aee4d31d5b
commit 40723a80a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 325 additions and 165 deletions

View File

@ -69,7 +69,7 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
@Override @Override
public void activate() { public void activate() {
TapoBridgeConfiguration config = bridge.getBridgeConfig(); TapoBridgeConfiguration config = bridge.getBridgeConfig();
if (config.cloudDiscoveryEnabled || config.udpDiscoveryEnabled) { if (config.cloudDiscovery) {
startBackgroundDiscovery(); startBackgroundDiscovery();
} }
} }
@ -148,12 +148,12 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
ThingUID bridgeUID = tapoBridge.getUID(); ThingUID bridgeUID = tapoBridge.getUID();
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC); ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC);
return DiscoveryResultBuilder.create(thingUID).withProperties(properties) return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withRepresentationProperty(DEVICE_REPRASENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label) .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
.build(); .build();
} else { } else {
ThingUID thingUID = new ThingUID(BINDING_ID, deviceMAC); ThingUID thingUID = new ThingUID(BINDING_ID, deviceMAC);
return DiscoveryResultBuilder.create(thingUID).withProperties(properties) return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withRepresentationProperty(DEVICE_REPRASENTATION_PROPERTY).withLabel(label).build(); .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withLabel(label).build();
} }
} }

View File

@ -235,6 +235,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
*/ */
protected void sendSecurePasstrhroug(String payload, String command) { protected void sendSecurePasstrhroug(String payload, String command) {
/* encrypt payload */ /* encrypt payload */
logger.trace("({}) encrypting payload '{}'", uid, payload);
String encryptedPayload = encryptPayload(payload); String encryptedPayload = encryptPayload(payload);
/* create secured payload */ /* create secured payload */

View File

@ -313,6 +313,8 @@ public class TapoDeviceHttpApi {
*/ */
protected void sendAsyncRequest(String url, String payload, String command) { protected void sendAsyncRequest(String url, String payload, String command) {
logger.trace("({}) sendAsncRequest to '{}' with cookie '{}'", uid, url, this.cookie); logger.trace("({}) sendAsncRequest to '{}' with cookie '{}'", uid, url, this.cookie);
logger.trace("({}) command/payload: '{}''{}'", uid, command, payload);
try { try {
Request httpRequest = bridge.getHttpClient().newRequest(url).method(HttpMethod.POST.toString()); Request httpRequest = bridge.getHttpClient().newRequest(url).method(HttpMethod.POST.toString());
@ -344,22 +346,27 @@ public class TapoDeviceHttpApi {
} else { } else {
/* request succesfull */ /* request succesfull */
String rBody = getContentAsString(); String rBody = getContentAsString();
rBody = decryptResponse(rBody); logger.trace("({}) receivedRespose '{}'", uid, rBody);
logger.trace("({}) requestCompleted '{}'", uid, rBody); if (!hasErrorCode(rBody)) {
/* handle result */ rBody = decryptResponse(rBody);
switch (command) { logger.trace("({}) decryptedResponse '{}'", uid, rBody);
case DEVICE_CMD_SETINFO: /* handle result */
handleSuccessResponse(rBody); switch (command) {
break; case DEVICE_CMD_SETINFO:
case DEVICE_CMD_GETINFO: handleSuccessResponse(rBody);
handleDeviceResult(rBody); break;
break; case DEVICE_CMD_GETINFO:
case DEVICE_CMD_GETENERGY: handleDeviceResult(rBody);
handleEnergyResult(rBody); break;
break; case DEVICE_CMD_GETENERGY:
case DEVICE_CMD_CUSTOM: handleEnergyResult(rBody);
handleCustomResponse(rBody); break;
break; case DEVICE_CMD_CUSTOM:
handleCustomResponse(rBody);
break;
}
} else {
getErrorCode(rBody);
} }
} }
} }
@ -411,6 +418,24 @@ public class TapoDeviceHttpApi {
} }
} }
/**
* Check for JsonObject "errorcode" and if this is > 0 (no Error)
*
* @param responseBody
* @return true if is js errorcode > 0; false if there is no "errorcode"
*/
protected Boolean hasErrorCode(String responseBody) {
if (isValidJson(responseBody)) {
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
/* get errocode (0=success) */
Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
if (errorCode > 0) {
return true;
}
}
return false;
}
/** /**
* SET HTTP-HEADERS * SET HTTP-HEADERS
*/ */

View File

@ -119,7 +119,7 @@ public class TapoThingConstants {
public static final String DEVICE_PROPERTY_USAGE_7 = "time_usage_past7"; public static final String DEVICE_PROPERTY_USAGE_7 = "time_usage_past7";
public static final String DEVICE_PROPERTY_USAGE_30 = "time_usage_past30"; public static final String DEVICE_PROPERTY_USAGE_30 = "time_usage_past30";
public static final String DEVICE_PROPERTY_USAGE_TODAY = "time_usage_today"; public static final String DEVICE_PROPERTY_USAGE_TODAY = "time_usage_today";
public static final String DEVICE_REPRASENTATION_PROPERTY = "macAddress"; public static final String DEVICE_REPRESENTATION_PROPERTY = "macAddress";
// lightning effects // lightning effects
public static final String DEVICE_PROPERTY_EFFECT = "lighting_effect"; public static final String DEVICE_PROPERTY_EFFECT = "lighting_effect";
public static final String PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS = "brightness"; public static final String PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS = "brightness";

View File

@ -49,7 +49,7 @@ import com.google.gson.JsonArray;
public class TapoBridgeHandler extends BaseBridgeHandler { public class TapoBridgeHandler extends BaseBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class); private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class);
private final TapoErrorHandler bridgeError = new TapoErrorHandler(); private final TapoErrorHandler bridgeError = new TapoErrorHandler();
private final TapoBridgeConfiguration config; private TapoBridgeConfiguration config = new TapoBridgeConfiguration();
private final HttpClient httpClient; private final HttpClient httpClient;
private @Nullable ScheduledFuture<?> startupJob; private @Nullable ScheduledFuture<?> startupJob;
private @Nullable ScheduledFuture<?> pollingJob; private @Nullable ScheduledFuture<?> pollingJob;
@ -64,7 +64,6 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
super(bridge); super(bridge);
Thing thing = getThing(); Thing thing = getThing();
this.cloudConnector = new TapoCloudConnector(this, httpClient); this.cloudConnector = new TapoCloudConnector(this, httpClient);
this.config = new TapoBridgeConfiguration(thing);
this.credentials = new TapoCredentials(); this.credentials = new TapoCredentials();
this.uid = thing.getUID().toString(); this.uid = thing.getUID().toString();
this.httpClient = httpClient; this.httpClient = httpClient;
@ -81,7 +80,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* set credentials and login cloud * set credentials and login cloud
*/ */
public void initialize() { public void initialize() {
this.config.loadSettings(); this.config = getConfigAs(TapoBridgeConfiguration.class);
this.credentials = new TapoCredentials(config.username, config.password); this.credentials = new TapoCredentials(config.username, config.password);
activateBridge(); activateBridge();
} }
@ -146,13 +145,15 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* Start CloudLogin Scheduler * Start CloudLogin Scheduler
*/ */
protected void startCloudScheduler() { protected void startCloudScheduler() {
Integer pollingInterval = config.cloudReconnectIntervalM; int pollingInterval = config.reconnectInterval;
TimeUnit timeUnit = TimeUnit.MINUTES;
if (pollingInterval > 0) { if (pollingInterval > 0) {
logger.trace("{} starting bridge cloud sheduler", this.uid); logger.debug("{} starting cloudScheduler with interval {} {}", this.uid, pollingInterval, timeUnit);
this.pollingJob = scheduler.scheduleWithFixedDelay(this::loginCloud, pollingInterval, pollingInterval, this.pollingJob = scheduler.scheduleWithFixedDelay(this::loginCloud, pollingInterval, pollingInterval,
TimeUnit.MINUTES); timeUnit);
} else { } else {
logger.debug("({}) cloudScheduler disabled with config '0'", uid);
stopScheduler(this.pollingJob); stopScheduler(this.pollingJob);
} }
} }
@ -161,13 +162,14 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* Start DeviceDiscovery Scheduler * Start DeviceDiscovery Scheduler
*/ */
protected void startDiscoveryScheduler() { protected void startDiscoveryScheduler() {
Integer pollingInterval = config.discoveryIntervalM; int pollingInterval = config.discoveryInterval;
if (config.cloudDiscoveryEnabled && pollingInterval > 0) { TimeUnit timeUnit = TimeUnit.MINUTES;
logger.trace("{} starting bridge discovery sheduler", this.uid); if (config.cloudDiscovery && pollingInterval > 0) {
logger.debug("{} starting discoveryScheduler with interval {} {}", this.uid, pollingInterval, timeUnit);
this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, timeUnit);
TimeUnit.MINUTES);
} else { } else {
logger.debug("({}) discoveryScheduler disabled with config '0'", uid);
stopScheduler(this.discoveryJob); stopScheduler(this.discoveryJob);
} }
} }
@ -254,7 +256,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
*/ */
public JsonArray getDeviceList() { public JsonArray getDeviceList() {
JsonArray deviceList = new JsonArray(); JsonArray deviceList = new JsonArray();
if (config.cloudDiscoveryEnabled) { if (config.cloudDiscovery) {
logger.trace("{} discover devicelist from cloud", this.uid); logger.trace("{} discover devicelist from cloud", this.uid);
deviceList = getDeviceListCloud(); deviceList = getDeviceListCloud();
} }

View File

@ -53,7 +53,7 @@ public abstract class TapoDevice extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(TapoDevice.class); private final Logger logger = LoggerFactory.getLogger(TapoDevice.class);
protected final TapoErrorHandler deviceError = new TapoErrorHandler(); protected final TapoErrorHandler deviceError = new TapoErrorHandler();
protected final String uid; protected final String uid;
protected TapoDeviceConfiguration config; protected TapoDeviceConfiguration config = new TapoDeviceConfiguration();
protected TapoDeviceInfo deviceInfo; protected TapoDeviceInfo deviceInfo;
protected @Nullable ScheduledFuture<?> startupJob; protected @Nullable ScheduledFuture<?> startupJob;
protected @Nullable ScheduledFuture<?> pollingJob; protected @Nullable ScheduledFuture<?> pollingJob;
@ -67,7 +67,6 @@ public abstract class TapoDevice extends BaseThingHandler {
*/ */
protected TapoDevice(Thing thing) { protected TapoDevice(Thing thing) {
super(thing); super(thing);
this.config = new TapoDeviceConfiguration(thing);
this.deviceInfo = new TapoDeviceInfo(); this.deviceInfo = new TapoDeviceInfo();
this.uid = getThing().getUID().getAsString(); this.uid = getThing().getUID().getAsString();
} }
@ -84,7 +83,7 @@ public abstract class TapoDevice extends BaseThingHandler {
@Override @Override
public void initialize() { public void initialize() {
try { try {
this.config.loadSettings(); this.config = getConfigAs(TapoDeviceConfiguration.class);
Bridge bridgeThing = getBridge(); Bridge bridgeThing = getBridge();
if (bridgeThing != null) { if (bridgeThing != null) {
BridgeHandler bridgeHandler = bridgeThing.getHandler(); BridgeHandler bridgeHandler = bridgeThing.getHandler();
@ -128,7 +127,6 @@ public abstract class TapoDevice extends BaseThingHandler {
// background initialization (delay it a little bit): // background initialization (delay it a little bit):
this.startupJob = scheduler.schedule(this::delayedStartUp, 2000, TimeUnit.MILLISECONDS); this.startupJob = scheduler.schedule(this::delayedStartUp, 2000, TimeUnit.MILLISECONDS);
startScheduler();
} }
/** /**
@ -180,22 +178,25 @@ public abstract class TapoDevice extends BaseThingHandler {
*/ */
private void delayedStartUp() { private void delayedStartUp() {
connect(); connect();
startPollingScheduler();
} }
/** /**
* Start scheduler * Start scheduler
*/ */
protected void startScheduler() { protected void startPollingScheduler() {
Integer pollingInterval = this.config.pollingInterval; int pollingInterval = this.config.pollingInterval;
TimeUnit timeUnit = TimeUnit.SECONDS;
if (pollingInterval > 0) { if (pollingInterval > 0) {
if (pollingInterval < POLLING_MIN_INTERVAL_S) { if (pollingInterval < POLLING_MIN_INTERVAL_S) {
pollingInterval = POLLING_MIN_INTERVAL_S; pollingInterval = POLLING_MIN_INTERVAL_S;
} }
logger.trace("({}) starScheduler: create job with interval : {}", uid, pollingInterval); logger.debug("({}) startScheduler: create job with interval : {} {}", uid, pollingInterval, timeUnit);
this.pollingJob = scheduler.scheduleWithFixedDelay(this::schedulerAction, pollingInterval, pollingInterval, this.pollingJob = scheduler.scheduleWithFixedDelay(this::pollingSchedulerAction, pollingInterval,
TimeUnit.SECONDS); pollingInterval, timeUnit);
} else { } else {
logger.debug("({}) scheduler disabled with config '0'", uid);
stopScheduler(this.pollingJob); stopScheduler(this.pollingJob);
} }
} }
@ -215,7 +216,7 @@ public abstract class TapoDevice extends BaseThingHandler {
/** /**
* Scheduler Action * Scheduler Action
*/ */
protected void schedulerAction() { protected void pollingSchedulerAction() {
logger.trace("({}) schedulerAction", uid); logger.trace("({}) schedulerAction", uid);
queryDeviceInfo(); queryDeviceInfo();
} }
@ -276,7 +277,7 @@ public abstract class TapoDevice extends BaseThingHandler {
*/ */
protected Boolean isExpectedThing(TapoDeviceInfo deviceInfo) { protected Boolean isExpectedThing(TapoDeviceInfo deviceInfo) {
try { try {
String expectedThingUID = getThing().getProperties().get(DEVICE_REPRASENTATION_PROPERTY); String expectedThingUID = getThing().getProperties().get(DEVICE_REPRESENTATION_PROPERTY);
String foundThingUID = deviceInfo.getRepresentationProperty(); String foundThingUID = deviceInfo.getRepresentationProperty();
String foundModel = deviceInfo.getModel(); String foundModel = deviceInfo.getModel();
if (expectedThingUID == null || expectedThingUID.isBlank()) { if (expectedThingUID == null || expectedThingUID.isBlank()) {

View File

@ -74,7 +74,9 @@ public class PayloadBuilder {
long timeMils = System.currentTimeMillis();// * 1000; long timeMils = System.currentTimeMillis();// * 1000;
payload.addProperty("method", this.method); payload.addProperty("method", this.method);
payload.add("params", this.parameters); if (this.parameters.size() > 0) {
payload.add("params", this.parameters);
}
payload.addProperty("requestTimeMils", timeMils); payload.addProperty("requestTimeMils", timeMils);
return payload; return payload;

View File

@ -13,10 +13,6 @@
package org.openhab.binding.tapocontrol.internal.structures; package org.openhab.binding.tapocontrol.internal.structures;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Thing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* The {@link TapoBridgeConfiguration} class contains fields mapping bridge configuration parameters. * The {@link TapoBridgeConfiguration} class contains fields mapping bridge configuration parameters.
@ -26,13 +22,9 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public final class TapoBridgeConfiguration { public final class TapoBridgeConfiguration {
private final Logger logger = LoggerFactory.getLogger(TapoBridgeConfiguration.class);
/* THING CONFIGUTATION PROPERTYS */ /* THING CONFIGUTATION PROPERTYS */
public static final String CONFIG_EMAIL = "username"; public static final String CONFIG_EMAIL = "username";
public static final String CONFIG_PASS = "password"; public static final String CONFIG_PASS = "password";
public static final String CONFIG_DEVICE_IP = "ipAddress";
public static final String CONFIG_UPDATE_INTERVAL = "pollingInterval";
public static final String CONFIG_DISCOVERY_CLOUD = "cloudDiscovery"; public static final String CONFIG_DISCOVERY_CLOUD = "cloudDiscovery";
public static final String CONFIG_DISCOVERY_INTERVAL = "discoveryInterval"; public static final String CONFIG_DISCOVERY_INTERVAL = "discoveryInterval";
@ -42,35 +34,7 @@ public final class TapoBridgeConfiguration {
/* thing configuration parameter. */ /* thing configuration parameter. */
public String username = ""; public String username = "";
public String password = ""; public String password = "";
public Boolean cloudDiscoveryEnabled = false; public boolean cloudDiscovery = false;
public Boolean udpDiscoveryEnabled = false; public int reconnectInterval = CONFIG_CLOUD_FIXED_INTERVAL;
public Integer cloudReconnectIntervalM = CONFIG_CLOUD_FIXED_INTERVAL; public int discoveryInterval = 60;
public Integer discoveryIntervalM = 30;
private Thing bridge;
/**
* Create settings
*
* @param thing BridgeThing
*/
public TapoBridgeConfiguration(Thing thing) {
this.bridge = thing;
loadSettings();
}
/**
* LOAD SETTINGS
*/
public void loadSettings() {
try {
Configuration config = this.bridge.getConfiguration();
username = config.get(CONFIG_EMAIL).toString();
password = config.get(CONFIG_PASS).toString();
cloudDiscoveryEnabled = Boolean.parseBoolean(config.get(CONFIG_DISCOVERY_CLOUD).toString());
discoveryIntervalM = Integer.valueOf(config.get(CONFIG_DISCOVERY_INTERVAL).toString());
} catch (Exception e) {
logger.warn("{} error reading configuration: '{}'", bridge.getUID(), e.getMessage());
}
}
} }

View File

@ -13,10 +13,6 @@
package org.openhab.binding.tapocontrol.internal.structures; package org.openhab.binding.tapocontrol.internal.structures;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Thing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* The {@link TapoDeviceConfiguration} class contains fields mapping bridge configuration parameters. * The {@link TapoDeviceConfiguration} class contains fields mapping bridge configuration parameters.
@ -26,38 +22,11 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public final class TapoDeviceConfiguration { public final class TapoDeviceConfiguration {
private final Logger logger = LoggerFactory.getLogger(TapoDeviceConfiguration.class);
/* THING CONFIGUTATION PROPERTYS */ /* THING CONFIGUTATION PROPERTYS */
public static final String CONFIG_DEVICE_IP = "ipAddress"; public static final String CONFIG_DEVICE_IP = "ipAddress";
public static final String CONFIG_UPDATE_INTERVAL = "pollingInterval"; public static final String CONFIG_UPDATE_INTERVAL = "pollingInterval";
/* thing configuration parameter. */ /* thing configuration parameter. */
public String ipAddress = ""; public String ipAddress = "";
public Integer pollingInterval = 30; public int pollingInterval = 30;
private final Thing device;
/**
* Create settings
*
* @param thing BridgeThing
*/
public TapoDeviceConfiguration(Thing thing) {
this.device = thing;
loadSettings();
}
/**
* LOAD SETTINGS
*/
public void loadSettings() {
try {
Configuration config = this.device.getConfiguration();
this.ipAddress = config.get(CONFIG_DEVICE_IP).toString();
this.pollingInterval = Integer.valueOf(config.get(CONFIG_UPDATE_INTERVAL).toString());
} catch (Exception e) {
logger.warn("{} error reading device-configuration: '{}'", device.getUID().toString(), e.getMessage());
}
}
} }

View File

@ -0,0 +1,231 @@
/**
* Copyright (c) 2010-2022 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.tapocontrol.internal;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.tapocontrol.internal.device.TapoBridgeHandler;
import org.openhab.binding.tapocontrol.internal.structures.TapoBridgeConfiguration;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.thing.Thing;
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.ThingHandlerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* Handler class for TAPO Smart Home thing discovery
*
* @author Christian Wild - Initial contribution
*/
@NonNullByDefault
public class TapoDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(TapoDiscoveryService.class);
protected @NonNullByDefault({}) TapoBridgeHandler bridge;
/***********************************
*
* INITIALIZATION
*
************************************/
/**
* INIT CLASS
*
* @param bridgeHandler
*/
public TapoDiscoveryService() {
super(SUPPORTED_THING_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false);
}
/**
* deactivate
*/
@Override
public void activate() {
TapoBridgeConfiguration config = bridge.getBridgeConfig();
if (config.cloudDiscovery || config.udpDiscovery) {
startBackgroundDiscovery();
}
}
/**
* deactivate
*/
@Override
public void deactivate() {
super.deactivate();
}
@Override
public void setThingHandler(@Nullable ThingHandler handler) {
if (handler instanceof TapoBridgeHandler) {
TapoBridgeHandler tapoBridge = (TapoBridgeHandler) handler;
tapoBridge.setDiscoveryService(this);
this.bridge = tapoBridge;
}
}
@Override
public @Nullable ThingHandler getThingHandler() {
return this.bridge;
}
/***********************************
*
* SCAN HANDLING
*
************************************/
/**
* Start scan manually
*/
@Override
public void startScan() {
removeOlderResults(getTimestampOfLastScan());
if (bridge != null) {
JsonArray jsonArray = bridge.getDeviceList();
handleCloudDevices(jsonArray);
}
}
/***********************************
*
* handle Results
*
************************************/
/**
* CREATE DISCOVERY RESULT
* creates discoveryResult (Thing) from JsonObject got from Cloud
*
* @param device JsonObject with device information
* @return DiscoveryResult-Object
*/
public DiscoveryResult createResult(JsonObject device) {
TapoBridgeHandler tapoBridge = this.bridge;
String deviceModel = getDeviceModel(device);
String label = getDeviceLabel(device);
String deviceMAC = device.get(CLOUD_PROPERTY_MAC).getAsString();
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
/* create properties */
Map<String, Object> properties = new HashMap<>();
properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_PROPERTY_FW).getAsString());
properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_PROPERTY_HW).getAsString());
properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_PROPERTY_ID).getAsString());
logger.debug("device {} discovered", deviceModel);
if (tapoBridge != null) {
ThingUID bridgeUID = tapoBridge.getUID();
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC);
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
.build();
} else {
ThingUID thingUID = new ThingUID(BINDING_ID, deviceMAC);
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withLabel(label).build();
}
}
/**
* work with result from get devices from cloud devices
*
* @param deviceList
*/
protected void handleCloudDevices(JsonArray deviceList) {
try {
for (JsonElement deviceElement : deviceList) {
if (deviceElement.isJsonObject()) {
JsonObject device = deviceElement.getAsJsonObject();
String deviceModel = getDeviceModel(device);
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
/* create thing */
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
DiscoveryResult discoveryResult = createResult(device);
thingDiscovered(discoveryResult);
}
}
}
} catch (Exception e) {
logger.debug("error handlling CloudDevices", e);
}
}
/**
* GET DEVICEMODEL
*
* @param device JsonObject with deviceData
* @return String with DeviceModel
*/
protected String getDeviceModel(JsonObject device) {
try {
String deviceModel = device.get(CLOUD_PROPERTY_MODEL).getAsString();
deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
deviceModel = deviceModel.replace("Tapo", "");
deviceModel = deviceModel.replace("Series", "");
deviceModel = deviceModel.trim();
deviceModel = deviceModel.replace(" ", "_");
return deviceModel;
} catch (Exception e) {
logger.debug("error getDeviceModel", e);
return "";
}
}
/**
* GET DEVICE LABEL
*
* @param device JsonObject with deviceData
* @return String with DeviceLabel
*/
protected String getDeviceLabel(JsonObject device) {
try {
String deviceLabel = "";
String deviceModel = getDeviceModel(device);
ThingTypeUID deviceUID = new ThingTypeUID(BINDING_ID, deviceModel);
if (SUPPORTED_SMART_PLUG_UIDS.contains(deviceUID)) {
deviceLabel = DEVICE_DESCRIPTION_SMART_PLUG;
} else if (SUPPORTED_WHITE_BULB_UIDS.contains(deviceUID)) {
deviceLabel = DEVICE_DESCRIPTION_WHITE_BULB;
} else if (SUPPORTED_COLOR_BULB_UIDS.contains(deviceUID)) {
deviceLabel = DEVICE_DESCRIPTION_COLOR_BULB;
}
return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel;
} catch (Exception e) {
logger.debug("error getDeviceLabel", e);
return "";
}
}
}

View File

@ -50,8 +50,8 @@ import com.google.gson.JsonArray;
public class TapoBridgeHandler extends BaseBridgeHandler { public class TapoBridgeHandler extends BaseBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class); private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class);
private final TapoErrorHandler bridgeError = new TapoErrorHandler(); private final TapoErrorHandler bridgeError = new TapoErrorHandler();
private final TapoBridgeConfiguration config;
private final HttpClient httpClient; private final HttpClient httpClient;
private TapoBridgeConfiguration config;
private @Nullable ScheduledFuture<?> startupJob; private @Nullable ScheduledFuture<?> startupJob;
private @Nullable ScheduledFuture<?> pollingJob; private @Nullable ScheduledFuture<?> pollingJob;
private @Nullable ScheduledFuture<?> discoveryJob; private @Nullable ScheduledFuture<?> discoveryJob;
@ -65,7 +65,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
super(bridge); super(bridge);
Thing thing = getThing(); Thing thing = getThing();
this.cloudConnector = new TapoCloudConnector(this, httpClient); this.cloudConnector = new TapoCloudConnector(this, httpClient);
this.config = new TapoBridgeConfiguration(thing); this.config = new TapoBridgeConfiguration();
this.credentials = new TapoCredentials(); this.credentials = new TapoCredentials();
this.uid = thing.getUID().toString(); this.uid = thing.getUID().toString();
this.httpClient = httpClient; this.httpClient = httpClient;
@ -82,7 +82,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* set credentials and login cloud * set credentials and login cloud
*/ */
public void initialize() { public void initialize() {
this.config.loadSettings(); this.config = getConfigAs(TapoBridgeConfiguration.class);
this.credentials = new TapoCredentials(config.username, config.password); this.credentials = new TapoCredentials(config.username, config.password);
activateBridge(); activateBridge();
} }
@ -147,7 +147,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* Start CloudLogin Scheduler * Start CloudLogin Scheduler
*/ */
protected void startCloudScheduler() { protected void startCloudScheduler() {
Integer pollingInterval = config.cloudReconnectIntervalM; Integer pollingInterval = config.reconnectInterval;
if (pollingInterval > 0) { if (pollingInterval > 0) {
logger.trace("{} starting bridge cloud sheduler", this.uid); logger.trace("{} starting bridge cloud sheduler", this.uid);
@ -162,8 +162,8 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
* Start DeviceDiscovery Scheduler * Start DeviceDiscovery Scheduler
*/ */
protected void startDiscoveryScheduler() { protected void startDiscoveryScheduler() {
Integer pollingInterval = config.discoveryIntervalM; Integer pollingInterval = config.discoveryInterval;
if (config.cloudDiscoveryEnabled && pollingInterval > 0) { if (config.cloudDiscovery && pollingInterval > 0) {
logger.trace("{} starting bridge discovery sheduler", this.uid); logger.trace("{} starting bridge discovery sheduler", this.uid);
this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval,
@ -255,10 +255,10 @@ public class TapoBridgeHandler extends BaseBridgeHandler {
*/ */
public JsonArray getDeviceList() { public JsonArray getDeviceList() {
JsonArray deviceList = new JsonArray(); JsonArray deviceList = new JsonArray();
if (config.cloudDiscoveryEnabled) { if (config.cloudDiscovery) {
logger.trace("{} discover devicelist from cloud", this.uid); logger.trace("{} discover devicelist from cloud", this.uid);
deviceList = getDeviceListCloud(); deviceList = getDeviceListCloud();
} else if (config.udpDiscoveryEnabled) { } else if (config.udpDiscovery) {
logger.trace("{} discover devicelist from udp", this.uid); logger.trace("{} discover devicelist from udp", this.uid);
deviceList = getDeviceListUDP(); deviceList = getDeviceListUDP();
} }

View File

@ -13,10 +13,6 @@
package org.openhab.binding.tapocontrol.internal.structures; package org.openhab.binding.tapocontrol.internal.structures;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Thing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* The {@link TapoBridgeConfiguration} class contains fields mapping bridge configuration parameters. * The {@link TapoBridgeConfiguration} class contains fields mapping bridge configuration parameters.
@ -26,52 +22,21 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public final class TapoBridgeConfiguration { public final class TapoBridgeConfiguration {
private final Logger logger = LoggerFactory.getLogger(TapoBridgeConfiguration.class);
/* THING CONFIGUTATION PROPERTYS */ /* THING CONFIGUTATION PROPERTYS */
public static final String CONFIG_EMAIL = "username"; public static final String CONFIG_EMAIL = "username";
public static final String CONFIG_PASS = "password"; public static final String CONFIG_PASS = "password";
public static final String CONFIG_DEVICE_IP = "ipAddress";
public static final String CONFIG_UPDATE_INTERVAL = "pollingInterval";
public static final String CONFIG_CLOUD_UPDATE_INTERVAL = "cloudReconnect";
public static final String CONFIG_DISCOVERY_CLOUD = "cloudDiscovery"; public static final String CONFIG_DISCOVERY_CLOUD = "cloudDiscovery";
public static final String CONFIG_DISCOVERY_UDP = "udpDiscovery"; public static final String CONFIG_DISCOVERY_UDP = "udpDiscovery";
public static final String CONFIG_DISCOVERY_INTERVAL = "discoveryInterval"; public static final String CONFIG_DISCOVERY_INTERVAL = "discoveryInterval";
/* DEFAULT & FIXED CONFIGURATIONS */
public static final Integer CONFIG_CLOUD_FIXED_INTERVAL = 1440;
/* thing configuration parameter. */ /* thing configuration parameter. */
public String username = ""; public String username = "";
public String password = ""; public String password = "";
public Boolean cloudDiscoveryEnabled = false; public boolean cloudDiscovery = false;
public Boolean udpDiscoveryEnabled = false; public boolean udpDiscovery = false;
public Integer cloudReconnectIntervalM = 1440; public int reconnectInterval = CONFIG_CLOUD_FIXED_INTERVAL;
public Integer discoveryIntervalM = 30; public int discoveryInterval = 60;
private Thing bridge;
/**
* Create settings
*
* @param thing BridgeThing
*/
public TapoBridgeConfiguration(Thing thing) {
this.bridge = thing;
loadSettings();
}
/**
* LOAD SETTINGS
*/
public void loadSettings() {
try {
Configuration config = this.bridge.getConfiguration();
username = config.get(CONFIG_EMAIL).toString();
password = config.get(CONFIG_PASS).toString();
cloudDiscoveryEnabled = Boolean.parseBoolean(config.get(CONFIG_DISCOVERY_CLOUD).toString());
udpDiscoveryEnabled = Boolean.parseBoolean(config.get(CONFIG_DISCOVERY_UDP).toString());
cloudReconnectIntervalM = Integer.valueOf(config.get(CONFIG_CLOUD_UPDATE_INTERVAL).toString());
discoveryIntervalM = Integer.valueOf(config.get(CONFIG_DISCOVERY_INTERVAL).toString());
} catch (Exception e) {
logger.warn("{} error reading configuration: '{}'", bridge.getUID(), e.getMessage());
}
}
} }