]> git.basschouten.com Git - openhab-addons.git/blob
9dcba16fcc75c769c86f0c3c26c67d76c5522941
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.gardena.internal.discovery;
14
15 import static org.openhab.binding.gardena.internal.GardenaBindingConstants.BINDING_ID;
16
17 import java.util.Collections;
18 import java.util.concurrent.CancellationException;
19 import java.util.concurrent.Future;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.gardena.internal.GardenaSmart;
26 import org.openhab.binding.gardena.internal.exception.GardenaException;
27 import org.openhab.binding.gardena.internal.handler.GardenaAccountHandler;
28 import org.openhab.binding.gardena.internal.model.Device;
29 import org.openhab.binding.gardena.internal.model.Location;
30 import org.openhab.binding.gardena.internal.util.UidUtils;
31 import org.openhab.core.config.discovery.AbstractDiscoveryService;
32 import org.openhab.core.config.discovery.DiscoveryResult;
33 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
34 import org.openhab.core.config.discovery.DiscoveryService;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingTypeUID;
37 import org.openhab.core.thing.ThingUID;
38 import org.openhab.core.thing.binding.ThingHandler;
39 import org.openhab.core.thing.binding.ThingHandlerService;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * The {@link GardenaDeviceDiscoveryService} is used to discover devices that are connected to Gardena Smart Home.
45  *
46  * @author Gerhard Riegler - Initial contribution
47  */
48 public class GardenaDeviceDiscoveryService extends AbstractDiscoveryService
49         implements DiscoveryService, ThingHandlerService {
50
51     private final Logger logger = LoggerFactory.getLogger(GardenaDeviceDiscoveryService.class);
52     private static final int DISCOVER_TIMEOUT_SECONDS = 30;
53
54     private @NonNullByDefault({}) GardenaAccountHandler accountHandler;
55     private Future<?> scanFuture;
56
57     public GardenaDeviceDiscoveryService() {
58         super(Collections.unmodifiableSet(Stream.of(new ThingTypeUID(BINDING_ID, "-")).collect(Collectors.toSet())),
59                 DISCOVER_TIMEOUT_SECONDS, false);
60     }
61
62     @Override
63     public void setThingHandler(@Nullable ThingHandler handler) {
64         if (handler instanceof GardenaAccountHandler) {
65             this.accountHandler = (GardenaAccountHandler) handler;
66             this.accountHandler.setDiscoveryService(this);
67         }
68     }
69
70     @Override
71     public @Nullable ThingHandler getThingHandler() {
72         return accountHandler;
73     }
74
75     /**
76      * Called on component activation.
77      */
78     @Override
79     public void activate() {
80         super.activate(null);
81     }
82
83     @Override
84     public void deactivate() {
85         super.deactivate();
86     }
87
88     @Override
89     protected void startScan() {
90         logger.debug("Starting Gardena discovery scan");
91         loadDevices();
92     }
93
94     @Override
95     public void stopScan() {
96         logger.debug("Stopping Gardena discovery scan");
97         if (scanFuture != null) {
98             scanFuture.cancel(true);
99         }
100         super.stopScan();
101     }
102
103     /**
104      * Starts a thread which loads all Gardena devices registered in the account
105      */
106     public void loadDevices() {
107         if (scanFuture == null) {
108             scanFuture = scheduler.submit(() -> {
109                 try {
110                     GardenaSmart gardena = accountHandler.getGardenaSmart();
111                     gardena.loadAllDevices();
112                     for (Location location : gardena.getLocations()) {
113                         for (String deviceId : location.getDeviceIds()) {
114                             deviceDiscovered(gardena.getDevice(deviceId));
115                         }
116                     }
117
118                     for (Thing thing : accountHandler.getThing().getThings()) {
119                         try {
120                             gardena.getDevice(UidUtils.getGardenaDeviceId(thing));
121                         } catch (GardenaException ex) {
122                             thingRemoved(thing.getUID());
123                         }
124                     }
125
126                     logger.debug("Finished Gardena device discovery scan on gateway '{}'",
127                             accountHandler.getGardenaSmart().getId());
128                 } catch (GardenaException ex) {
129                     logger.error("{}", ex.getMessage(), ex);
130                 } finally {
131                     scanFuture = null;
132                     removeOlderResults(getTimestampOfLastScan());
133                 }
134             });
135         } else {
136             logger.debug("Gardena device discovery scan in progress");
137         }
138     }
139
140     /**
141      * Waits for the discovery scan to finish and then returns.
142      */
143     public void waitForScanFinishing() {
144         if (scanFuture != null) {
145             logger.debug("Waiting for finishing Gardena device discovery scan");
146             try {
147                 scanFuture.get();
148                 logger.debug("Gardena device discovery scan finished");
149             } catch (CancellationException ex) {
150                 // ignore
151             } catch (Exception ex) {
152                 logger.error("Error waiting for device discovery scan: {}", ex.getMessage(), ex);
153             }
154         }
155     }
156
157     /**
158      * Generates the DiscoveryResult from a Gardena device.
159      */
160     public void deviceDiscovered(Device device) {
161         ThingUID accountUID = accountHandler.getThing().getUID();
162         ThingUID thingUID = UidUtils.generateThingUID(device, accountHandler.getThing());
163
164         DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(accountUID)
165                 .withLabel(device.getName()).build();
166         thingDiscovered(discoveryResult);
167     }
168
169     /**
170      * Removes the Gardena device.
171      */
172     public void deviceRemoved(Device device) {
173         ThingUID thingUID = UidUtils.generateThingUID(device, accountHandler.getThing());
174         thingRemoved(thingUID);
175     }
176 }