diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoDiscoveryService.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoDiscoveryService.java index 096baec68..f13bfc7f7 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoDiscoveryService.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoDiscoveryService.java @@ -69,7 +69,7 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th @Override public void activate() { TapoBridgeConfiguration config = bridge.getBridgeConfig(); - if (config.cloudDiscoveryEnabled || config.udpDiscoveryEnabled) { + if (config.cloudDiscovery) { startBackgroundDiscovery(); } } @@ -148,12 +148,12 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th ThingUID bridgeUID = tapoBridge.getUID(); ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC); return DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withRepresentationProperty(DEVICE_REPRASENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label) + .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_REPRASENTATION_PROPERTY).withLabel(label).build(); + .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withLabel(label).build(); } } diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java index 55f82ff15..d8184e08c 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java @@ -235,6 +235,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi { */ protected void sendSecurePasstrhroug(String payload, String command) { /* encrypt payload */ + logger.trace("({}) encrypting payload '{}'", uid, payload); String encryptedPayload = encryptPayload(payload); /* create secured payload */ diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java index eb4966f16..211c895fe 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java @@ -313,6 +313,8 @@ public class TapoDeviceHttpApi { */ protected void sendAsyncRequest(String url, String payload, String command) { logger.trace("({}) sendAsncRequest to '{}' with cookie '{}'", uid, url, this.cookie); + logger.trace("({}) command/payload: '{}''{}'", uid, command, payload); + try { Request httpRequest = bridge.getHttpClient().newRequest(url).method(HttpMethod.POST.toString()); @@ -344,22 +346,27 @@ public class TapoDeviceHttpApi { } else { /* request succesfull */ String rBody = getContentAsString(); - rBody = decryptResponse(rBody); - logger.trace("({}) requestCompleted '{}'", uid, rBody); - /* handle result */ - switch (command) { - case DEVICE_CMD_SETINFO: - handleSuccessResponse(rBody); - break; - case DEVICE_CMD_GETINFO: - handleDeviceResult(rBody); - break; - case DEVICE_CMD_GETENERGY: - handleEnergyResult(rBody); - break; - case DEVICE_CMD_CUSTOM: - handleCustomResponse(rBody); - break; + logger.trace("({}) receivedRespose '{}'", uid, rBody); + if (!hasErrorCode(rBody)) { + rBody = decryptResponse(rBody); + logger.trace("({}) decryptedResponse '{}'", uid, rBody); + /* handle result */ + switch (command) { + case DEVICE_CMD_SETINFO: + handleSuccessResponse(rBody); + break; + case DEVICE_CMD_GETINFO: + handleDeviceResult(rBody); + break; + case DEVICE_CMD_GETENERGY: + handleEnergyResult(rBody); + 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 */ diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java index 4898acff4..b2422668e 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java @@ -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_30 = "time_usage_past30"; 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 public static final String DEVICE_PROPERTY_EFFECT = "lighting_effect"; public static final String PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS = "brightness"; diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java index bf9b150af..832f1dfdf 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java @@ -49,7 +49,7 @@ import com.google.gson.JsonArray; public class TapoBridgeHandler extends BaseBridgeHandler { private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class); private final TapoErrorHandler bridgeError = new TapoErrorHandler(); - private final TapoBridgeConfiguration config; + private TapoBridgeConfiguration config = new TapoBridgeConfiguration(); private final HttpClient httpClient; private @Nullable ScheduledFuture<?> startupJob; private @Nullable ScheduledFuture<?> pollingJob; @@ -64,7 +64,6 @@ public class TapoBridgeHandler extends BaseBridgeHandler { super(bridge); Thing thing = getThing(); this.cloudConnector = new TapoCloudConnector(this, httpClient); - this.config = new TapoBridgeConfiguration(thing); this.credentials = new TapoCredentials(); this.uid = thing.getUID().toString(); this.httpClient = httpClient; @@ -81,7 +80,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * set credentials and login cloud */ public void initialize() { - this.config.loadSettings(); + this.config = getConfigAs(TapoBridgeConfiguration.class); this.credentials = new TapoCredentials(config.username, config.password); activateBridge(); } @@ -146,13 +145,15 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * Start CloudLogin Scheduler */ protected void startCloudScheduler() { - Integer pollingInterval = config.cloudReconnectIntervalM; + int pollingInterval = config.reconnectInterval; + TimeUnit timeUnit = TimeUnit.MINUTES; 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, - TimeUnit.MINUTES); + timeUnit); } else { + logger.debug("({}) cloudScheduler disabled with config '0'", uid); stopScheduler(this.pollingJob); } } @@ -161,13 +162,14 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * Start DeviceDiscovery Scheduler */ protected void startDiscoveryScheduler() { - Integer pollingInterval = config.discoveryIntervalM; - if (config.cloudDiscoveryEnabled && pollingInterval > 0) { - logger.trace("{} starting bridge discovery sheduler", this.uid); + int pollingInterval = config.discoveryInterval; + TimeUnit timeUnit = TimeUnit.MINUTES; + if (config.cloudDiscovery && pollingInterval > 0) { + logger.debug("{} starting discoveryScheduler with interval {} {}", this.uid, pollingInterval, timeUnit); - this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, - TimeUnit.MINUTES); + this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, timeUnit); } else { + logger.debug("({}) discoveryScheduler disabled with config '0'", uid); stopScheduler(this.discoveryJob); } } @@ -254,7 +256,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler { */ public JsonArray getDeviceList() { JsonArray deviceList = new JsonArray(); - if (config.cloudDiscoveryEnabled) { + if (config.cloudDiscovery) { logger.trace("{} discover devicelist from cloud", this.uid); deviceList = getDeviceListCloud(); } diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java index eb46638f7..d3f13eb2b 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java @@ -53,7 +53,7 @@ public abstract class TapoDevice extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(TapoDevice.class); protected final TapoErrorHandler deviceError = new TapoErrorHandler(); protected final String uid; - protected TapoDeviceConfiguration config; + protected TapoDeviceConfiguration config = new TapoDeviceConfiguration(); protected TapoDeviceInfo deviceInfo; protected @Nullable ScheduledFuture<?> startupJob; protected @Nullable ScheduledFuture<?> pollingJob; @@ -67,7 +67,6 @@ public abstract class TapoDevice extends BaseThingHandler { */ protected TapoDevice(Thing thing) { super(thing); - this.config = new TapoDeviceConfiguration(thing); this.deviceInfo = new TapoDeviceInfo(); this.uid = getThing().getUID().getAsString(); } @@ -84,7 +83,7 @@ public abstract class TapoDevice extends BaseThingHandler { @Override public void initialize() { try { - this.config.loadSettings(); + this.config = getConfigAs(TapoDeviceConfiguration.class); Bridge bridgeThing = getBridge(); if (bridgeThing != null) { BridgeHandler bridgeHandler = bridgeThing.getHandler(); @@ -128,7 +127,6 @@ public abstract class TapoDevice extends BaseThingHandler { // background initialization (delay it a little bit): this.startupJob = scheduler.schedule(this::delayedStartUp, 2000, TimeUnit.MILLISECONDS); - startScheduler(); } /** @@ -180,22 +178,25 @@ public abstract class TapoDevice extends BaseThingHandler { */ private void delayedStartUp() { connect(); + startPollingScheduler(); } /** * Start scheduler */ - protected void startScheduler() { - Integer pollingInterval = this.config.pollingInterval; + protected void startPollingScheduler() { + int pollingInterval = this.config.pollingInterval; + TimeUnit timeUnit = TimeUnit.SECONDS; if (pollingInterval > 0) { if (pollingInterval < POLLING_MIN_INTERVAL_S) { pollingInterval = POLLING_MIN_INTERVAL_S; } - logger.trace("({}) starScheduler: create job with interval : {}", uid, pollingInterval); - this.pollingJob = scheduler.scheduleWithFixedDelay(this::schedulerAction, pollingInterval, pollingInterval, - TimeUnit.SECONDS); + logger.debug("({}) startScheduler: create job with interval : {} {}", uid, pollingInterval, timeUnit); + this.pollingJob = scheduler.scheduleWithFixedDelay(this::pollingSchedulerAction, pollingInterval, + pollingInterval, timeUnit); } else { + logger.debug("({}) scheduler disabled with config '0'", uid); stopScheduler(this.pollingJob); } } @@ -215,7 +216,7 @@ public abstract class TapoDevice extends BaseThingHandler { /** * Scheduler Action */ - protected void schedulerAction() { + protected void pollingSchedulerAction() { logger.trace("({}) schedulerAction", uid); queryDeviceInfo(); } @@ -276,7 +277,7 @@ public abstract class TapoDevice extends BaseThingHandler { */ protected Boolean isExpectedThing(TapoDeviceInfo deviceInfo) { try { - String expectedThingUID = getThing().getProperties().get(DEVICE_REPRASENTATION_PROPERTY); + String expectedThingUID = getThing().getProperties().get(DEVICE_REPRESENTATION_PROPERTY); String foundThingUID = deviceInfo.getRepresentationProperty(); String foundModel = deviceInfo.getModel(); if (expectedThingUID == null || expectedThingUID.isBlank()) { diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/PayloadBuilder.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/PayloadBuilder.java index 943de45e4..26ed9e064 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/PayloadBuilder.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/PayloadBuilder.java @@ -74,7 +74,9 @@ public class PayloadBuilder { long timeMils = System.currentTimeMillis();// * 1000; payload.addProperty("method", this.method); - payload.add("params", this.parameters); + if (this.parameters.size() > 0) { + payload.add("params", this.parameters); + } payload.addProperty("requestTimeMils", timeMils); return payload; diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java index 39b7d2d3f..5d639a1ab 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java @@ -13,10 +13,6 @@ package org.openhab.binding.tapocontrol.internal.structures; 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. @@ -26,13 +22,9 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public final class TapoBridgeConfiguration { - private final Logger logger = LoggerFactory.getLogger(TapoBridgeConfiguration.class); - /* THING CONFIGUTATION PROPERTYS */ public static final String CONFIG_EMAIL = "username"; 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_INTERVAL = "discoveryInterval"; @@ -42,35 +34,7 @@ public final class TapoBridgeConfiguration { /* thing configuration parameter. */ public String username = ""; public String password = ""; - public Boolean cloudDiscoveryEnabled = false; - public Boolean udpDiscoveryEnabled = false; - public Integer cloudReconnectIntervalM = CONFIG_CLOUD_FIXED_INTERVAL; - 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()); - } - } + public boolean cloudDiscovery = false; + public int reconnectInterval = CONFIG_CLOUD_FIXED_INTERVAL; + public int discoveryInterval = 60; } diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoDeviceConfiguration.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoDeviceConfiguration.java index 9b68f0944..f344c0a6f 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoDeviceConfiguration.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoDeviceConfiguration.java @@ -13,10 +13,6 @@ package org.openhab.binding.tapocontrol.internal.structures; 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. @@ -26,38 +22,11 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public final class TapoDeviceConfiguration { - private final Logger logger = LoggerFactory.getLogger(TapoDeviceConfiguration.class); - /* THING CONFIGUTATION PROPERTYS */ public static final String CONFIG_DEVICE_IP = "ipAddress"; public static final String CONFIG_UPDATE_INTERVAL = "pollingInterval"; /* thing configuration parameter. */ public String ipAddress = ""; - public Integer 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()); - } - } + public int pollingInterval = 30; } diff --git a/bundles/org.openhab.binding.tapocontrol/src/test/TapoDiscoveryService.java b/bundles/org.openhab.binding.tapocontrol/src/test/TapoDiscoveryService.java new file mode 100644 index 000000000..3c02a7c0d --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/test/TapoDiscoveryService.java @@ -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 ""; + } + } +} diff --git a/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java b/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java index c5600de8c..c84ef500c 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java +++ b/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/device/TapoBridgeHandler.java @@ -50,8 +50,8 @@ import com.google.gson.JsonArray; public class TapoBridgeHandler extends BaseBridgeHandler { private final Logger logger = LoggerFactory.getLogger(TapoBridgeHandler.class); private final TapoErrorHandler bridgeError = new TapoErrorHandler(); - private final TapoBridgeConfiguration config; private final HttpClient httpClient; + private TapoBridgeConfiguration config; private @Nullable ScheduledFuture<?> startupJob; private @Nullable ScheduledFuture<?> pollingJob; private @Nullable ScheduledFuture<?> discoveryJob; @@ -65,7 +65,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler { super(bridge); Thing thing = getThing(); this.cloudConnector = new TapoCloudConnector(this, httpClient); - this.config = new TapoBridgeConfiguration(thing); + this.config = new TapoBridgeConfiguration(); this.credentials = new TapoCredentials(); this.uid = thing.getUID().toString(); this.httpClient = httpClient; @@ -82,7 +82,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * set credentials and login cloud */ public void initialize() { - this.config.loadSettings(); + this.config = getConfigAs(TapoBridgeConfiguration.class); this.credentials = new TapoCredentials(config.username, config.password); activateBridge(); } @@ -147,7 +147,7 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * Start CloudLogin Scheduler */ protected void startCloudScheduler() { - Integer pollingInterval = config.cloudReconnectIntervalM; + Integer pollingInterval = config.reconnectInterval; if (pollingInterval > 0) { logger.trace("{} starting bridge cloud sheduler", this.uid); @@ -162,8 +162,8 @@ public class TapoBridgeHandler extends BaseBridgeHandler { * Start DeviceDiscovery Scheduler */ protected void startDiscoveryScheduler() { - Integer pollingInterval = config.discoveryIntervalM; - if (config.cloudDiscoveryEnabled && pollingInterval > 0) { + Integer pollingInterval = config.discoveryInterval; + if (config.cloudDiscovery && pollingInterval > 0) { logger.trace("{} starting bridge discovery sheduler", this.uid); this.discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 0, pollingInterval, @@ -255,10 +255,10 @@ public class TapoBridgeHandler extends BaseBridgeHandler { */ public JsonArray getDeviceList() { JsonArray deviceList = new JsonArray(); - if (config.cloudDiscoveryEnabled) { + if (config.cloudDiscovery) { logger.trace("{} discover devicelist from cloud", this.uid); deviceList = getDeviceListCloud(); - } else if (config.udpDiscoveryEnabled) { + } else if (config.udpDiscovery) { logger.trace("{} discover devicelist from udp", this.uid); deviceList = getDeviceListUDP(); } diff --git a/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java b/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java index 13b039da3..f53fcd15f 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java +++ b/bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/structures/TapoBridgeConfiguration.java @@ -13,10 +13,6 @@ package org.openhab.binding.tapocontrol.internal.structures; 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. @@ -26,52 +22,21 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public final class TapoBridgeConfiguration { - private final Logger logger = LoggerFactory.getLogger(TapoBridgeConfiguration.class); - /* THING CONFIGUTATION PROPERTYS */ public static final String CONFIG_EMAIL = "username"; 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_UDP = "udpDiscovery"; public static final String CONFIG_DISCOVERY_INTERVAL = "discoveryInterval"; + /* DEFAULT & FIXED CONFIGURATIONS */ + public static final Integer CONFIG_CLOUD_FIXED_INTERVAL = 1440; + /* thing configuration parameter. */ public String username = ""; public String password = ""; - public Boolean cloudDiscoveryEnabled = false; - public Boolean udpDiscoveryEnabled = false; - public Integer cloudReconnectIntervalM = 1440; - 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()); - 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()); - } - } + public boolean cloudDiscovery = false; + public boolean udpDiscovery = false; + public int reconnectInterval = CONFIG_CLOUD_FIXED_INTERVAL; + public int discoveryInterval = 60; }