2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.tapocontrol.internal;
15 import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
16 import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
17 import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
19 import java.util.HashMap;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.openhab.binding.tapocontrol.internal.device.TapoBridgeHandler;
24 import org.openhab.binding.tapocontrol.internal.structures.TapoBridgeConfiguration;
25 import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
26 import org.openhab.core.config.discovery.DiscoveryResult;
27 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
28 import org.openhab.core.config.discovery.DiscoveryService;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.osgi.service.component.annotations.Component;
33 import org.osgi.service.component.annotations.ServiceScope;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.gson.JsonArray;
38 import com.google.gson.JsonElement;
39 import com.google.gson.JsonObject;
42 * Handler class for TAPO Smart Home thing discovery
44 * @author Christian Wild - Initial contribution
46 @Component(scope = ServiceScope.PROTOTYPE, service = TapoDiscoveryService.class)
48 public class TapoDiscoveryService extends AbstractThingHandlerDiscoveryService<TapoBridgeHandler> {
49 private final Logger logger = LoggerFactory.getLogger(TapoDiscoveryService.class);
51 /***********************************
55 ************************************/
60 public TapoDiscoveryService() {
61 super(TapoBridgeHandler.class, SUPPORTED_THING_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false);
65 public void initialize() {
66 thingHandler.setDiscoveryService(this);
67 TapoBridgeConfiguration config = thingHandler.getBridgeConfig();
68 modified(Map.of(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, config.cloudDiscovery));
72 /***********************************
76 ************************************/
82 public void startScan() {
83 removeOlderResults(getTimestampOfLastScan());
84 JsonArray jsonArray = thingHandler.getDeviceList();
85 handleCloudDevices(jsonArray);
88 /***********************************
92 ************************************/
95 * CREATE DISCOVERY RESULT
96 * creates discoveryResult (Thing) from JsonObject got from Cloud
98 * @param device JsonObject with device information
99 * @return DiscoveryResult-Object
101 public DiscoveryResult createResult(JsonObject device) {
102 String deviceModel = getDeviceModel(device);
103 String label = getDeviceLabel(device);
104 String deviceMAC = device.get(CLOUD_JSON_KEY_MAC).getAsString();
105 ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
107 /* create properties */
108 Map<String, Object> properties = new HashMap<>();
109 properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
110 properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
111 properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_JSON_KEY_FW).getAsString());
112 properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_JSON_KEY_HW).getAsString());
113 properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
114 properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_JSON_KEY_ID).getAsString());
116 logger.debug("device {} discovered", deviceModel);
117 ThingUID bridgeUID = thingHandler.getUID();
118 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC);
119 return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
120 .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
125 * work with result from get devices from cloud devices
129 protected void handleCloudDevices(JsonArray deviceList) {
131 for (JsonElement deviceElement : deviceList) {
132 if (deviceElement.isJsonObject()) {
133 JsonObject device = deviceElement.getAsJsonObject();
134 String deviceModel = getDeviceModel(device);
135 ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
138 if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
139 DiscoveryResult discoveryResult = createResult(device);
140 thingDiscovered(discoveryResult);
144 } catch (Exception e) {
145 logger.debug("error handling CloudDevices", e);
152 * @param device JsonObject with deviceData
153 * @return String with DeviceModel
155 protected String getDeviceModel(JsonObject device) {
157 String deviceModel = device.get(CLOUD_JSON_KEY_MODEL).getAsString();
158 deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
159 deviceModel = deviceModel.replace("Tapo", "");
160 deviceModel = deviceModel.replace("Series", "");
161 deviceModel = deviceModel.trim();
162 deviceModel = deviceModel.replace(" ", "_");
164 } catch (Exception e) {
165 logger.debug("error getDeviceModel", e);
173 * @param device JsonObject with deviceData
174 * @return String with DeviceLabel
176 protected String getDeviceLabel(JsonObject device) {
178 String deviceLabel = "";
179 String deviceModel = getDeviceModel(device);
180 ThingTypeUID deviceUID = new ThingTypeUID(BINDING_ID, deviceModel);
182 if (SUPPORTED_SMART_PLUG_UIDS.contains(deviceUID)) {
183 deviceLabel = DEVICE_DESCRIPTION_SMART_PLUG;
184 } else if (SUPPORTED_WHITE_BULB_UIDS.contains(deviceUID)) {
185 deviceLabel = DEVICE_DESCRIPTION_WHITE_BULB;
186 } else if (SUPPORTED_COLOR_BULB_UIDS.contains(deviceUID)) {
187 deviceLabel = DEVICE_DESCRIPTION_COLOR_BULB;
189 return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel;
190 } catch (Exception e) {
191 logger.debug("error getDeviceLabel", e);