]> git.basschouten.com Git - openhab-addons.git/blob
d69a041a56bae63422768242eb70549c82cf7c59
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.amazonechocontrol.internal.discovery;
14
15 import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*;
16
17 import java.util.Date;
18 import java.util.HashMap;
19 import java.util.Hashtable;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.ScheduledFuture;
24 import java.util.concurrent.TimeUnit;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.amazonechocontrol.internal.Connection;
29 import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
30 import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler;
31 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDeviceAlias;
32 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.DriverIdentity;
33 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice;
34 import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup;
35 import org.openhab.binding.amazonechocontrol.internal.jsons.SmartHomeBaseDevice;
36 import org.openhab.binding.amazonechocontrol.internal.smarthome.Constants;
37 import org.openhab.core.config.discovery.AbstractDiscoveryService;
38 import org.openhab.core.config.discovery.DiscoveryResult;
39 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
40 import org.openhab.core.thing.ThingUID;
41 import org.osgi.service.component.annotations.Activate;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * @author Lukas Knoeller - Initial contribution
47  */
48 @NonNullByDefault
49 public class SmartHomeDevicesDiscovery extends AbstractDiscoveryService {
50     private AccountHandler accountHandler;
51     private final Logger logger = LoggerFactory.getLogger(SmartHomeDevicesDiscovery.class);
52
53     private @Nullable ScheduledFuture<?> startScanStateJob;
54     private @Nullable Long activateTimeStamp;
55
56     public SmartHomeDevicesDiscovery(AccountHandler accountHandler) {
57         super(SUPPORTED_SMART_HOME_THING_TYPES_UIDS, 10);
58         this.accountHandler = accountHandler;
59     }
60
61     public void activate() {
62         activate(new Hashtable<String, Object>());
63     }
64
65     @Override
66     public void deactivate() {
67         super.deactivate();
68     }
69
70     @Override
71     protected void startScan() {
72         stopScanJob();
73         Long activateTimeStamp = this.activateTimeStamp;
74         if (activateTimeStamp != null) {
75             removeOlderResults(activateTimeStamp);
76         }
77         setSmartHomeDevices(accountHandler.updateSmartHomeDeviceList(false));
78     }
79
80     protected void startAutomaticScan() {
81         if (!this.accountHandler.getThing().getThings().isEmpty()) {
82             stopScanJob();
83             return;
84         }
85         Connection connection = this.accountHandler.findConnection();
86         if (connection == null) {
87             return;
88         }
89         Date verifyTime = connection.tryGetVerifyTime();
90         if (verifyTime == null) {
91             return;
92         }
93         if (new Date().getTime() - verifyTime.getTime() < 10000) {
94             return;
95         }
96         startScan();
97     }
98
99     @Override
100     protected void startBackgroundDiscovery() {
101         stopScanJob();
102         startScanStateJob = scheduler.scheduleWithFixedDelay(this::startAutomaticScan, 3000, 1000,
103                 TimeUnit.MILLISECONDS);
104     }
105
106     @Override
107     protected void stopBackgroundDiscovery() {
108         stopScanJob();
109     }
110
111     void stopScanJob() {
112         ScheduledFuture<?> currentStartScanStateJob = startScanStateJob;
113         if (currentStartScanStateJob != null) {
114             currentStartScanStateJob.cancel(false);
115             startScanStateJob = null;
116         }
117         super.stopScan();
118     }
119
120     @Override
121     @Activate
122     public void activate(@Nullable Map<String, Object> config) {
123         super.activate(config);
124         if (config != null) {
125             modified(config);
126         }
127         Long activateTimeStamp = this.activateTimeStamp;
128         if (activateTimeStamp == null) {
129             this.activateTimeStamp = new Date().getTime();
130         }
131     };
132
133     synchronized void setSmartHomeDevices(List<SmartHomeBaseDevice> deviceList) {
134         int smartHomeDeviceDiscoveryMode = accountHandler.getSmartHomeDevicesDiscoveryMode();
135         if (smartHomeDeviceDiscoveryMode == 0) {
136             return;
137         }
138
139         for (Object smartHomeDevice : deviceList) {
140             ThingUID bridgeThingUID = this.accountHandler.getThing().getUID();
141             ThingUID thingUID = null;
142             String deviceName = null;
143             Map<String, Object> props = new HashMap<>();
144
145             if (smartHomeDevice instanceof SmartHomeDevice) {
146                 SmartHomeDevice shd = (SmartHomeDevice) smartHomeDevice;
147                 logger.trace("Found SmartHome device: {}", shd);
148
149                 String entityId = shd.entityId;
150                 if (entityId == null) {
151                     // No entity id
152                     continue;
153                 }
154                 String id = shd.findId();
155                 if (id == null) {
156                     // No id
157                     continue;
158                 }
159                 boolean isSkillDevice = false;
160                 DriverIdentity driverIdentity = shd.driverIdentity;
161                 isSkillDevice = driverIdentity != null && "SKILL".equals(driverIdentity.namespace);
162
163                 if (smartHomeDeviceDiscoveryMode == 1 && isSkillDevice) {
164                     // Connected through skill
165                     continue;
166                 }
167                 if (!(smartHomeDeviceDiscoveryMode == 2) && "openHAB".equalsIgnoreCase(shd.manufacturerName)) {
168                     // OpenHAB device
169                     continue;
170                 }
171
172                 if (shd.getCapabilities().stream()
173                         .noneMatch(capability -> Constants.SUPPORTED_INTERFACES.contains(capability.interfaceName))) {
174                     // No supported interface found
175                     continue;
176                 }
177
178                 thingUID = new ThingUID(THING_TYPE_SMART_HOME_DEVICE, bridgeThingUID, entityId.replace(".", "-"));
179
180                 List<JsonSmartHomeDeviceAlias> aliases = shd.aliases;
181                 if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
182                         && "SonarCloudService".equals(driverIdentity.identifier)) {
183                     deviceName = "Alexa Guard on " + shd.friendlyName;
184                 } else if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
185                         && "OnGuardSmartHomeBridgeService".equals(driverIdentity.identifier)) {
186                     deviceName = "Alexa Guard";
187                 } else if (aliases != null && !aliases.isEmpty() && aliases.get(0).friendlyName != null) {
188                     deviceName = aliases.get(0).friendlyName;
189                 } else {
190                     deviceName = shd.friendlyName;
191                 }
192                 props.put(DEVICE_PROPERTY_ID, id);
193             } else if (smartHomeDevice instanceof SmartHomeGroup) {
194                 SmartHomeGroup shg = (SmartHomeGroup) smartHomeDevice;
195                 logger.trace("Found SmartHome device: {}", shg);
196
197                 String id = shg.findId();
198                 if (id == null) {
199                     // No id
200                     continue;
201                 }
202                 Set<SmartHomeDevice> supportedChildren = SmartHomeDeviceHandler.getSupportedSmartHomeDevices(shg,
203                         deviceList);
204                 if (supportedChildren.size() == 0) {
205                     // No children with an supported interface
206                     continue;
207                 }
208                 thingUID = new ThingUID(THING_TYPE_SMART_HOME_DEVICE_GROUP, bridgeThingUID, id.replace(".", "-"));
209                 deviceName = shg.applianceGroupName;
210                 props.put(DEVICE_PROPERTY_ID, id);
211             }
212
213             if (thingUID != null) {
214                 DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withLabel(deviceName)
215                         .withProperties(props).withBridge(bridgeThingUID).build();
216
217                 logger.debug("Device [{}] found.", deviceName);
218
219                 thingDiscovered(result);
220             }
221         }
222     }
223 }