2 * Copyright (c) 2010-2024 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.tado.internal.discovery;
15 import static org.openhab.binding.tado.internal.TadoBindingConstants.*;
17 import java.io.IOException;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.List;
23 import java.util.concurrent.ScheduledFuture;
24 import java.util.concurrent.TimeUnit;
25 import java.util.stream.Collectors;
26 import java.util.stream.Stream;
28 import org.eclipse.jdt.annotation.NonNullByDefault;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.openhab.binding.tado.internal.TadoBindingConstants;
31 import org.openhab.binding.tado.internal.api.ApiException;
32 import org.openhab.binding.tado.internal.api.model.MobileDevice;
33 import org.openhab.binding.tado.internal.api.model.Zone;
34 import org.openhab.binding.tado.internal.handler.TadoHomeHandler;
35 import org.openhab.core.config.discovery.AbstractDiscoveryService;
36 import org.openhab.core.config.discovery.DiscoveryResult;
37 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
38 import org.openhab.core.thing.ThingTypeUID;
39 import org.openhab.core.thing.ThingUID;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * Discovery service for zones and mobile devices.
46 * @author Dennis Frommknecht - Initial contribution
49 public class TadoDiscoveryService extends AbstractDiscoveryService {
50 private static final int TIMEOUT = 5;
51 private static final long REFRESH = 600;
53 private final Logger logger = LoggerFactory.getLogger(TadoDiscoveryService.class);
55 private @Nullable ScheduledFuture<?> discoveryFuture;
57 public static final Set<ThingTypeUID> DISCOVERABLE_THING_TYPES_UIDS = Collections
58 .unmodifiableSet(Stream.of(THING_TYPE_ZONE, THING_TYPE_MOBILE_DEVICE).collect(Collectors.toSet()));
60 private TadoHomeHandler homeHandler;
62 public TadoDiscoveryService(TadoHomeHandler tadoHomeHandler) {
63 super(DISCOVERABLE_THING_TYPES_UIDS, TIMEOUT);
64 this.homeHandler = tadoHomeHandler;
67 public void activate() {
72 public void deactivate() {
77 protected void startScan() {
78 if (homeHandler.getHomeId() == null) {
83 discoverMobileDevices();
87 protected void startBackgroundDiscovery() {
88 logger.debug("Start Tado background discovery");
89 ScheduledFuture<?> discoveryFuture = this.discoveryFuture;
90 if (discoveryFuture == null || discoveryFuture.isCancelled()) {
91 logger.debug("Start Scan");
92 this.discoveryFuture = scheduler.scheduleWithFixedDelay(this::startScan, 30, REFRESH, TimeUnit.SECONDS);
97 protected void stopBackgroundDiscovery() {
98 logger.debug("Stop Tado background discovery");
99 ScheduledFuture<?> discoveryFuture = this.discoveryFuture;
100 if (discoveryFuture != null && !discoveryFuture.isCancelled()) {
101 discoveryFuture.cancel(true);
105 private void discoverZones() {
106 Long homeId = homeHandler.getHomeId();
108 if (homeId == null) {
109 logger.debug("Could not discover tado zones: Missing home id");
114 List<Zone> zoneList = homeHandler.getApi().listZones(homeId);
116 if (zoneList != null) {
117 for (Zone zone : zoneList) {
118 notifyZoneDiscovery(homeId, zone);
121 } catch (IOException | ApiException e) {
122 logger.debug("Could not discover tado zones: {}", e.getMessage(), e);
126 private void notifyZoneDiscovery(Long homeId, Zone zone) {
127 Integer zoneId = zone.getId();
129 ThingUID bridgeUID = this.homeHandler.getThing().getUID();
130 ThingUID uid = new ThingUID(TadoBindingConstants.THING_TYPE_ZONE, bridgeUID, zoneId.toString());
132 Map<String, Object> properties = new HashMap<>();
133 properties.put(CONFIG_ZONE_ID, zoneId);
135 DiscoveryResult result = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID).withLabel(zone.getName())
136 .withProperties(properties).withRepresentationProperty(CONFIG_ZONE_ID).build();
138 thingDiscovered(result);
140 logger.debug("Discovered zone '{}' with id {} ({})", zone.getName(), zoneId.toString(), uid);
143 private void discoverMobileDevices() {
144 Long homeId = homeHandler.getHomeId();
146 if (homeId == null) {
147 logger.debug("Could not discover mobile devices: Missing home id");
152 List<MobileDevice> mobileDeviceList = homeHandler.getApi().listMobileDevices(homeId);
154 if (mobileDeviceList != null) {
155 for (MobileDevice mobileDevice : mobileDeviceList) {
156 if (mobileDevice.getSettings().isGeoTrackingEnabled()) {
157 notifyMobileDeviceDiscovery(homeId, mobileDevice);
161 } catch (IOException | ApiException e) {
162 logger.debug("Could not discover mobile devices: {}", e.getMessage(), e);
166 private void notifyMobileDeviceDiscovery(Long homeId, MobileDevice device) {
167 ThingUID bridgeUID = this.homeHandler.getThing().getUID();
168 ThingUID uid = new ThingUID(TadoBindingConstants.THING_TYPE_MOBILE_DEVICE, bridgeUID,
169 device.getId().toString());
171 Map<String, Object> properties = new HashMap<>();
172 properties.put(CONFIG_MOBILE_DEVICE_ID, device.getId());
174 DiscoveryResult result = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID).withLabel(device.getName())
175 .withProperties(properties).withRepresentationProperty(CONFIG_MOBILE_DEVICE_ID).build();
177 thingDiscovered(result);
179 logger.debug("Discovered mobile device '{}' with id {} ({})", device.getName(), device.getId().toString(), uid);