]> git.basschouten.com Git - openhab-addons.git/blob
feba4e0edeed9e746171988b3ffe040840cdc733
[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     public TapoDiscoveryService() {
61         super(SUPPORTED_THING_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false);
62     }
63
64     /**
65      * activate
66      */
67     @Override
68     public void activate() {
69         TapoBridgeConfiguration config = bridge.getBridgeConfig();
70         if (config.cloudDiscovery) {
71             startBackgroundDiscovery();
72         }
73     }
74
75     /**
76      * deactivate
77      */
78     @Override
79     public void deactivate() {
80         super.deactivate();
81     }
82
83     @Override
84     public void setThingHandler(@Nullable ThingHandler handler) {
85         if (handler instanceof TapoBridgeHandler tapoBridge) {
86             tapoBridge.setDiscoveryService(this);
87             this.bridge = tapoBridge;
88         }
89     }
90
91     @Override
92     public @Nullable ThingHandler getThingHandler() {
93         return this.bridge;
94     }
95
96     /***********************************
97      *
98      * SCAN HANDLING
99      *
100      ************************************/
101
102     /**
103      * Start scan manually
104      */
105     @Override
106     public void startScan() {
107         removeOlderResults(getTimestampOfLastScan());
108         if (bridge != null) {
109             JsonArray jsonArray = bridge.getDeviceList();
110             handleCloudDevices(jsonArray);
111         }
112     }
113
114     /***********************************
115      *
116      * handle Results
117      *
118      ************************************/
119
120     /**
121      * CREATE DISCOVERY RESULT
122      * creates discoveryResult (Thing) from JsonObject got from Cloud
123      * 
124      * @param device JsonObject with device information
125      * @return DiscoveryResult-Object
126      */
127     public DiscoveryResult createResult(JsonObject device) {
128         TapoBridgeHandler tapoBridge = this.bridge;
129         String deviceModel = getDeviceModel(device);
130         String label = getDeviceLabel(device);
131         String deviceMAC = device.get(CLOUD_JSON_KEY_MAC).getAsString();
132         ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
133
134         /* create properties */
135         Map<String, Object> properties = new HashMap<>();
136         properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
137         properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
138         properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_JSON_KEY_FW).getAsString());
139         properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_JSON_KEY_HW).getAsString());
140         properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
141         properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_JSON_KEY_ID).getAsString());
142
143         logger.debug("device {} discovered", deviceModel);
144         if (tapoBridge != null) {
145             ThingUID bridgeUID = tapoBridge.getUID();
146             ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, deviceMAC);
147             return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
148                     .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
149                     .build();
150         } else {
151             ThingUID thingUID = new ThingUID(BINDING_ID, deviceMAC);
152             return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
153                     .withRepresentationProperty(DEVICE_REPRESENTATION_PROPERTY).withLabel(label).build();
154         }
155     }
156
157     /**
158      * work with result from get devices from cloud devices
159      * 
160      * @param deviceList
161      */
162     protected void handleCloudDevices(JsonArray deviceList) {
163         try {
164             for (JsonElement deviceElement : deviceList) {
165                 if (deviceElement.isJsonObject()) {
166                     JsonObject device = deviceElement.getAsJsonObject();
167                     String deviceModel = getDeviceModel(device);
168                     ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
169
170                     /* create thing */
171                     if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
172                         DiscoveryResult discoveryResult = createResult(device);
173                         thingDiscovered(discoveryResult);
174                     }
175                 }
176             }
177         } catch (Exception e) {
178             logger.debug("error handling CloudDevices", e);
179         }
180     }
181
182     /**
183      * GET DEVICEMODEL
184      * 
185      * @param device JsonObject with deviceData
186      * @return String with DeviceModel
187      */
188     protected String getDeviceModel(JsonObject device) {
189         try {
190             String deviceModel = device.get(CLOUD_JSON_KEY_MODEL).getAsString();
191             deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
192             deviceModel = deviceModel.replace("Tapo", "");
193             deviceModel = deviceModel.replace("Series", "");
194             deviceModel = deviceModel.trim();
195             deviceModel = deviceModel.replace(" ", "_");
196             return deviceModel;
197         } catch (Exception e) {
198             logger.debug("error getDeviceModel", e);
199             return "";
200         }
201     }
202
203     /**
204      * GET DEVICE LABEL
205      * 
206      * @param device JsonObject with deviceData
207      * @return String with DeviceLabel
208      */
209     protected String getDeviceLabel(JsonObject device) {
210         try {
211             String deviceLabel = "";
212             String deviceModel = getDeviceModel(device);
213             ThingTypeUID deviceUID = new ThingTypeUID(BINDING_ID, deviceModel);
214
215             if (SUPPORTED_SMART_PLUG_UIDS.contains(deviceUID)) {
216                 deviceLabel = DEVICE_DESCRIPTION_SMART_PLUG;
217             } else if (SUPPORTED_WHITE_BULB_UIDS.contains(deviceUID)) {
218                 deviceLabel = DEVICE_DESCRIPTION_WHITE_BULB;
219             } else if (SUPPORTED_COLOR_BULB_UIDS.contains(deviceUID)) {
220                 deviceLabel = DEVICE_DESCRIPTION_COLOR_BULB;
221             }
222             return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel;
223         } catch (Exception e) {
224             logger.debug("error getDeviceLabel", e);
225             return "";
226         }
227     }
228 }