]> git.basschouten.com Git - openhab-addons.git/blob
e6557de8be994ebe5edf2aee8b333aa6bbb2ebf7
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.AbstractThingHandlerDiscoveryService;
32 import org.openhab.core.config.discovery.DiscoveryResult;
33 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
34 import org.openhab.core.thing.Thing;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.ThingUID;
37 import org.osgi.service.component.annotations.Component;
38 import org.osgi.service.component.annotations.ServiceScope;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link GardenaDeviceDiscoveryService} is used to discover devices that are connected to Gardena smart system.
44  *
45  * @author Gerhard Riegler - Initial contribution
46  */
47 @Component(scope = ServiceScope.PROTOTYPE, service = GardenaDeviceDiscoveryService.class)
48 @NonNullByDefault
49 public class GardenaDeviceDiscoveryService extends AbstractThingHandlerDiscoveryService<GardenaAccountHandler> {
50
51     private final Logger logger = LoggerFactory.getLogger(GardenaDeviceDiscoveryService.class);
52     private static final int DISCOVER_TIMEOUT_SECONDS = 5;
53     private @Nullable Future<?> scanFuture;
54
55     public GardenaDeviceDiscoveryService() {
56         super(GardenaAccountHandler.class,
57                 Collections.unmodifiableSet(Stream.of(new ThingTypeUID(BINDING_ID, "-")).collect(Collectors.toSet())),
58                 DISCOVER_TIMEOUT_SECONDS, false);
59     }
60
61     @Override
62     public void initialize() {
63         thingHandler.setDiscoveryService(this);
64         super.initialize();
65     }
66
67     @Override
68     protected void startScan() {
69         logger.debug("Starting Gardena discovery scan");
70         loadDevices();
71     }
72
73     @Override
74     public void stopScan() {
75         logger.debug("Stopping Gardena discovery scan");
76         final Future<?> scanFuture = this.scanFuture;
77         if (scanFuture != null) {
78             scanFuture.cancel(true);
79         }
80         super.stopScan();
81     }
82
83     /**
84      * Starts a thread which loads all Gardena devices registered in the account.
85      */
86     private void loadDevices() {
87         if (scanFuture == null) {
88             scanFuture = scheduler.submit(() -> {
89                 GardenaSmart gardena = thingHandler.getGardenaSmart();
90                 if (gardena != null) {
91                     for (Device device : gardena.getAllDevices()) {
92                         deviceDiscovered(device);
93                     }
94
95                     for (Thing thing : thingHandler.getThing().getThings()) {
96                         try {
97                             gardena.getDevice(UidUtils.getGardenaDeviceId(thing));
98                         } catch (GardenaException ex) {
99                             thingRemoved(thing.getUID());
100                         }
101                     }
102
103                     logger.debug("Finished Gardena device discovery scan on gateway '{}'", gardena.getId());
104                     scanFuture = null;
105                     removeOlderResults(getTimestampOfLastScan());
106                 }
107             });
108         } else {
109             logger.debug("Gardena device discovery scan in progress");
110         }
111     }
112
113     /**
114      * Waits for the discovery scan to finish and then returns.
115      */
116     public void waitForScanFinishing() {
117         final Future<?> scanFuture = this.scanFuture;
118         if (scanFuture != null) {
119             logger.debug("Waiting for finishing Gardena device discovery scan");
120             try {
121                 scanFuture.get();
122                 logger.debug("Gardena device discovery scan finished");
123             } catch (CancellationException ex) {
124                 // ignore
125             } catch (Exception ex) {
126                 logger.error("Error waiting for device discovery scan: {}", ex.getMessage(), ex);
127             }
128         }
129     }
130
131     /**
132      * Generates the DiscoveryResult from a Gardena device.
133      */
134     public void deviceDiscovered(Device device) {
135         if (device.active) {
136             ThingUID accountUID = thingHandler.getThing().getUID();
137             ThingUID thingUID = UidUtils.generateThingUID(device, thingHandler.getThing());
138
139             try {
140                 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(accountUID)
141                         .withLabel(PropertyUtils.getPropertyValue(device, "common.attributes.name.value", String.class))
142                         .withProperty("id", device.id).withProperty("type", device.deviceType)
143                         .withRepresentationProperty("id").build();
144                 thingDiscovered(discoveryResult);
145             } catch (GardenaException ex) {
146                 logger.warn("{}", ex.getMessage());
147             }
148         }
149     }
150 }