]> git.basschouten.com Git - openhab-addons.git/blob
88a6dbf3dc8c178a9a00d8db7ce9736e470596ed
[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.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.dto.Device;
29 import org.openhab.binding.gardena.internal.util.PropertyUtils;
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 system.
45  *
46  * @author Gerhard Riegler - Initial contribution
47  */
48 @NonNullByDefault
49 public class GardenaDeviceDiscoveryService extends AbstractDiscoveryService
50         implements DiscoveryService, ThingHandlerService {
51
52     private final Logger logger = LoggerFactory.getLogger(GardenaDeviceDiscoveryService.class);
53     private static final int DISCOVER_TIMEOUT_SECONDS = 5;
54
55     private @NonNullByDefault({}) GardenaAccountHandler accountHandler;
56     private @Nullable Future<?> scanFuture;
57
58     public GardenaDeviceDiscoveryService() {
59         super(Collections.unmodifiableSet(Stream.of(new ThingTypeUID(BINDING_ID, "-")).collect(Collectors.toSet())),
60                 DISCOVER_TIMEOUT_SECONDS, false);
61     }
62
63     @Override
64     public void setThingHandler(@Nullable ThingHandler handler) {
65         if (handler instanceof GardenaAccountHandler) {
66             this.accountHandler = (GardenaAccountHandler) handler;
67             this.accountHandler.setDiscoveryService(this);
68         }
69     }
70
71     @Override
72     public @Nullable ThingHandler getThingHandler() {
73         return accountHandler;
74     }
75
76     /**
77      * Called on component activation.
78      */
79     @Override
80     public void activate() {
81         super.activate(null);
82     }
83
84     @Override
85     public void deactivate() {
86         super.deactivate();
87     }
88
89     @Override
90     protected void startScan() {
91         logger.debug("Starting Gardena discovery scan");
92         loadDevices();
93     }
94
95     @Override
96     public void stopScan() {
97         logger.debug("Stopping Gardena discovery scan");
98         final Future<?> scanFuture = this.scanFuture;
99         if (scanFuture != null) {
100             scanFuture.cancel(true);
101         }
102         super.stopScan();
103     }
104
105     /**
106      * Starts a thread which loads all Gardena devices registered in the account.
107      */
108     private void loadDevices() {
109         if (scanFuture == null) {
110             scanFuture = scheduler.submit(() -> {
111                 GardenaSmart gardena = accountHandler.getGardenaSmart();
112                 if (gardena != null) {
113                     for (Device device : gardena.getAllDevices()) {
114                         deviceDiscovered(device);
115                     }
116
117                     for (Thing thing : accountHandler.getThing().getThings()) {
118                         try {
119                             gardena.getDevice(UidUtils.getGardenaDeviceId(thing));
120                         } catch (GardenaException ex) {
121                             thingRemoved(thing.getUID());
122                         }
123                     }
124
125                     logger.debug("Finished Gardena device discovery scan on gateway '{}'", gardena.getId());
126                     scanFuture = null;
127                     removeOlderResults(getTimestampOfLastScan());
128                 }
129             });
130         } else {
131             logger.debug("Gardena device discovery scan in progress");
132         }
133     }
134
135     /**
136      * Waits for the discovery scan to finish and then returns.
137      */
138     public void waitForScanFinishing() {
139         final Future<?> scanFuture = this.scanFuture;
140         if (scanFuture != null) {
141             logger.debug("Waiting for finishing Gardena device discovery scan");
142             try {
143                 scanFuture.get();
144                 logger.debug("Gardena device discovery scan finished");
145             } catch (CancellationException ex) {
146                 // ignore
147             } catch (Exception ex) {
148                 logger.error("Error waiting for device discovery scan: {}", ex.getMessage(), ex);
149             }
150         }
151     }
152
153     /**
154      * Generates the DiscoveryResult from a Gardena device.
155      */
156     public void deviceDiscovered(Device device) {
157         if (device.active) {
158             ThingUID accountUID = accountHandler.getThing().getUID();
159             ThingUID thingUID = UidUtils.generateThingUID(device, accountHandler.getThing());
160
161             try {
162                 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(accountUID)
163                         .withLabel(PropertyUtils.getPropertyValue(device, "common.attributes.name.value", String.class))
164                         .withProperty("id", device.id).withProperty("type", device.deviceType)
165                         .withRepresentationProperty("id").build();
166                 thingDiscovered(discoveryResult);
167             } catch (GardenaException ex) {
168                 logger.warn("{}", ex.getMessage());
169             }
170         }
171     }
172 }