]> git.basschouten.com Git - openhab-addons.git/blob
73ccf282baadda7db44fbf0197de9cd9000cac8f
[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.spotify.internal.discovery;
14
15 import static org.openhab.binding.spotify.internal.SpotifyBindingConstants.*;
16
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.spotify.internal.SpotifyAccountHandler;
27 import org.openhab.binding.spotify.internal.SpotifyBindingConstants;
28 import org.openhab.binding.spotify.internal.api.model.Device;
29 import org.openhab.core.config.discovery.AbstractDiscoveryService;
30 import org.openhab.core.config.discovery.DiscoveryResult;
31 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
32 import org.openhab.core.config.discovery.DiscoveryService;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.thing.binding.ThingHandler;
36 import org.openhab.core.thing.binding.ThingHandlerService;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * The {@link SpotifyDeviceDiscoveryService} queries the Spotify Web API for available devices.
42  *
43  * @author Andreas Stenlund - Initial contribution
44  * @author Hilbrand Bouwkamp - Simplfied code to make call to shared code
45  */
46 @NonNullByDefault
47 public class SpotifyDeviceDiscoveryService extends AbstractDiscoveryService
48         implements DiscoveryService, ThingHandlerService {
49
50     // id for device is derived by stripping id of device with this length
51     private static final int PLAYER_ID_LENGTH = 4;
52     // Only devices can be discovered. A bridge must be manually added.
53     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_DEVICE);
54     // The call to listDevices is fast
55     private static final int DISCOVERY_TIME_SECONDS = 10;
56     // Check every minute for new devices
57     private static final long BACKGROUND_SCAN_REFRESH_MINUTES = 1;
58
59     private final Logger logger = LoggerFactory.getLogger(SpotifyDeviceDiscoveryService.class);
60
61     private @NonNullByDefault({}) SpotifyAccountHandler bridgeHandler;
62     private @NonNullByDefault({}) ThingUID bridgeUID;
63
64     private @Nullable ScheduledFuture<?> backgroundFuture;
65
66     public SpotifyDeviceDiscoveryService() {
67         super(SUPPORTED_THING_TYPES_UIDS, DISCOVERY_TIME_SECONDS);
68     }
69
70     @Override
71     public Set<ThingTypeUID> getSupportedThingTypes() {
72         return SUPPORTED_THING_TYPES_UIDS;
73     }
74
75     @Override
76     public void activate() {
77         Map<String, Object> properties = new HashMap<>();
78         properties.put(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, Boolean.TRUE);
79         super.activate(properties);
80     }
81
82     @Override
83     public void deactivate() {
84         super.deactivate();
85     }
86
87     @Override
88     public void setThingHandler(@Nullable ThingHandler handler) {
89         if (handler instanceof SpotifyAccountHandler) {
90             bridgeHandler = (SpotifyAccountHandler) handler;
91             bridgeUID = bridgeHandler.getUID();
92         }
93     }
94
95     @Override
96     public @Nullable ThingHandler getThingHandler() {
97         return bridgeHandler;
98     }
99
100     @Override
101     protected synchronized void startBackgroundDiscovery() {
102         stopBackgroundDiscovery();
103         backgroundFuture = scheduler.scheduleWithFixedDelay(this::startScan, BACKGROUND_SCAN_REFRESH_MINUTES,
104                 BACKGROUND_SCAN_REFRESH_MINUTES, TimeUnit.MINUTES);
105     }
106
107     @Override
108     protected synchronized void stopBackgroundDiscovery() {
109         if (backgroundFuture != null) {
110             backgroundFuture.cancel(true);
111             backgroundFuture = null;
112         }
113     }
114
115     @Override
116     protected void startScan() {
117         // If the bridge is not online no other thing devices can be found, so no reason to scan at this moment.
118         removeOlderResults(getTimestampOfLastScan());
119         if (bridgeHandler.isOnline()) {
120             logger.debug("Starting Spotify Device discovery for bridge {}", bridgeUID);
121             try {
122                 bridgeHandler.listDevices().forEach(this::thingDiscovered);
123             } catch (RuntimeException e) {
124                 logger.debug("Finding devices failed with message: {}", e.getMessage(), e);
125             }
126         }
127     }
128
129     private void thingDiscovered(Device device) {
130         Map<String, Object> properties = new HashMap<>();
131
132         properties.put(PROPERTY_SPOTIFY_DEVICE_NAME, device.getName());
133         ThingUID thing = new ThingUID(SpotifyBindingConstants.THING_TYPE_DEVICE, bridgeUID,
134                 device.getId().substring(0, PLAYER_ID_LENGTH));
135
136         DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thing).withBridge(bridgeUID)
137                 .withProperties(properties).withRepresentationProperty(PROPERTY_SPOTIFY_DEVICE_NAME)
138                 .withLabel(device.getName()).build();
139
140         thingDiscovered(discoveryResult);
141     }
142 }