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