]> git.basschouten.com Git - openhab-addons.git/blob
d0284ad3123021ad2215c278681a0c82419ff975
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.tapocontrol.internal;
14
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.*;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.tapocontrol.internal.device.TapoBridgeHandler;
25 import org.openhab.binding.tapocontrol.internal.structures.TapoBridgeConfiguration;
26 import org.openhab.core.config.discovery.AbstractDiscoveryService;
27 import org.openhab.core.config.discovery.DiscoveryResult;
28 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.openhab.core.thing.binding.ThingHandler;
33 import org.openhab.core.thing.binding.ThingHandlerService;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.gson.JsonArray;
38 import com.google.gson.JsonElement;
39 import com.google.gson.JsonObject;
40
41 /**
42  * Handler class for TAPO Smart Home thing discovery
43  *
44  * @author Christian Wild - Initial contribution
45  */
46 @NonNullByDefault
47 public class TapoDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
48     private final Logger logger = LoggerFactory.getLogger(TapoDiscoveryService.class);
49     protected @NonNullByDefault({}) TapoBridgeHandler bridge;
50
51     /***********************************
52      *
53      * INITIALIZATION
54      *
55      ************************************/
56
57     /**
58      * INIT CLASS
59      * 
60      * @param bridgeHandler
61      */
62     public TapoDiscoveryService() {
63         super(SUPPORTED_THING_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false);
64     }
65
66     /**
67      * activate
68      */
69     @Override
70     public void activate() {
71         TapoBridgeConfiguration config = bridge.getBridgeConfig();
72         if (config.cloudDiscovery) {
73             startBackgroundDiscovery();
74         }
75     }
76
77     /**
78      * deactivate
79      */
80     @Override
81     public void deactivate() {
82         super.deactivate();
83     }
84
85     @Override
86     public void setThingHandler(@Nullable ThingHandler handler) {
87         if (handler instanceof TapoBridgeHandler) {
88             TapoBridgeHandler tapoBridge = (TapoBridgeHandler) handler;
89             tapoBridge.setDiscoveryService(this);
90             this.bridge = tapoBridge;
91         }
92     }
93
94     @Override
95     public @Nullable ThingHandler getThingHandler() {
96         return this.bridge;
97     }
98
99     /***********************************
100      *
101      * SCAN HANDLING
102      *
103      ************************************/
104
105     /**
106      * Start scan manually
107      */
108     @Override
109     public void startScan() {
110         removeOlderResults(getTimestampOfLastScan());
111         if (bridge != null) {
112             JsonArray jsonArray = bridge.getDeviceList();
113             handleCloudDevices(jsonArray);
114         }
115     }
116
117     /***********************************
118      *
119      * handle Results
120      *
121      ************************************/
122
123     /**
124      * CREATE DISCOVERY RESULT
125      * creates discoveryResult (Thing) from JsonObject got from Cloud
126      * 
127      * @param device JsonObject with device information
128      * @return DiscoveryResult-Object
129      */
130     public DiscoveryResult createResult(JsonObject device) {
131         TapoBridgeHandler tapoBridge = this.bridge;
132         String deviceModel = getDeviceModel(device);
133         String label = getDeviceLabel(device);
134         String deviceMAC = device.get(CLOUD_JSON_KEY_MAC).getAsString();
135         ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
136
137         /* create properties */
138         Map<String, Object> properties = new HashMap<>();
139         properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
140         properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
141         properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_JSON_KEY_FW).getAsString());
142         properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_JSON_KEY_HW).getAsString());
143         properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
144         properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_JSON_KEY_ID).getAsString());
145
146         logger.debug("device {} discovered", deviceModel);
147         if (tapoBridge != null) {
148             ThingUID bridgeUID = tapoBridge.getUID();
149             ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC);
150             return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
151                     .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
152                     .build();
153         } else {
154             ThingUID thingUID = new ThingUID(BINDING_ID, deviceMAC);
155             return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
156                     .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withLabel(label).build();
157         }
158     }
159
160     /**
161      * work with result from get devices from cloud devices
162      * 
163      * @param deviceList
164      */
165     protected void handleCloudDevices(JsonArray deviceList) {
166         try {
167             for (JsonElement deviceElement : deviceList) {
168                 if (deviceElement.isJsonObject()) {
169                     JsonObject device = deviceElement.getAsJsonObject();
170                     String deviceModel = getDeviceModel(device);
171                     ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
172
173                     /* create thing */
174                     if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
175                         DiscoveryResult discoveryResult = createResult(device);
176                         thingDiscovered(discoveryResult);
177                     }
178                 }
179             }
180         } catch (Exception e) {
181             logger.debug("error handling CloudDevices", e);
182         }
183     }
184
185     /**
186      * GET DEVICEMODEL
187      * 
188      * @param device JsonObject with deviceData
189      * @return String with DeviceModel
190      */
191     protected String getDeviceModel(JsonObject device) {
192         try {
193             String deviceModel = device.get(CLOUD_JSON_KEY_MODEL).getAsString();
194             deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
195             deviceModel = deviceModel.replace("Tapo", "");
196             deviceModel = deviceModel.replace("Series", "");
197             deviceModel = deviceModel.trim();
198             deviceModel = deviceModel.replace(" ", "_");
199             return deviceModel;
200         } catch (Exception e) {
201             logger.debug("error getDeviceModel", e);
202             return "";
203         }
204     }
205
206     /**
207      * GET DEVICE LABEL
208      * 
209      * @param device JsonObject with deviceData
210      * @return String with DeviceLabel
211      */
212     protected String getDeviceLabel(JsonObject device) {
213         try {
214             String deviceLabel = "";
215             String deviceModel = getDeviceModel(device);
216             ThingTypeUID deviceUID = new ThingTypeUID(BINDING_ID, deviceModel);
217
218             if (SUPPORTED_SMART_PLUG_UIDS.contains(deviceUID)) {
219                 deviceLabel = DEVICE_DESCRIPTION_SMART_PLUG;
220             } else if (SUPPORTED_WHITE_BULB_UIDS.contains(deviceUID)) {
221                 deviceLabel = DEVICE_DESCRIPTION_WHITE_BULB;
222             } else if (SUPPORTED_COLOR_BULB_UIDS.contains(deviceUID)) {
223                 deviceLabel = DEVICE_DESCRIPTION_COLOR_BULB;
224             }
225             return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel;
226         } catch (Exception e) {
227             logger.debug("error getDeviceLabel", e);
228             return "";
229         }
230     }
231 }