2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.gardena.internal.discovery;
15 import static org.openhab.binding.gardena.internal.GardenaBindingConstants.BINDING_ID;
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;
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;
44 * The {@link GardenaDeviceDiscoveryService} is used to discover devices that are connected to Gardena smart system.
46 * @author Gerhard Riegler - Initial contribution
49 public class GardenaDeviceDiscoveryService extends AbstractDiscoveryService
50 implements DiscoveryService, ThingHandlerService {
52 private final Logger logger = LoggerFactory.getLogger(GardenaDeviceDiscoveryService.class);
53 private static final int DISCOVER_TIMEOUT_SECONDS = 5;
55 private @NonNullByDefault({}) GardenaAccountHandler accountHandler;
56 private @Nullable Future<?> scanFuture;
58 public GardenaDeviceDiscoveryService() {
59 super(Collections.unmodifiableSet(Stream.of(new ThingTypeUID(BINDING_ID, "-")).collect(Collectors.toSet())),
60 DISCOVER_TIMEOUT_SECONDS, false);
64 public void setThingHandler(@Nullable ThingHandler handler) {
65 if (handler instanceof GardenaAccountHandler gardenaAccountHandler) {
66 this.accountHandler = gardenaAccountHandler;
67 this.accountHandler.setDiscoveryService(this);
72 public @Nullable ThingHandler getThingHandler() {
73 return accountHandler;
77 * Called on component activation.
80 public void activate() {
85 public void deactivate() {
90 protected void startScan() {
91 logger.debug("Starting Gardena discovery scan");
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);
106 * Starts a thread which loads all Gardena devices registered in the account.
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);
117 for (Thing thing : accountHandler.getThing().getThings()) {
119 gardena.getDevice(UidUtils.getGardenaDeviceId(thing));
120 } catch (GardenaException ex) {
121 thingRemoved(thing.getUID());
125 logger.debug("Finished Gardena device discovery scan on gateway '{}'", gardena.getId());
127 removeOlderResults(getTimestampOfLastScan());
131 logger.debug("Gardena device discovery scan in progress");
136 * Waits for the discovery scan to finish and then returns.
138 public void waitForScanFinishing() {
139 final Future<?> scanFuture = this.scanFuture;
140 if (scanFuture != null) {
141 logger.debug("Waiting for finishing Gardena device discovery scan");
144 logger.debug("Gardena device discovery scan finished");
145 } catch (CancellationException ex) {
147 } catch (Exception ex) {
148 logger.error("Error waiting for device discovery scan: {}", ex.getMessage(), ex);
154 * Generates the DiscoveryResult from a Gardena device.
156 public void deviceDiscovered(Device device) {
158 ThingUID accountUID = accountHandler.getThing().getUID();
159 ThingUID thingUID = UidUtils.generateThingUID(device, accountHandler.getThing());
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());