]> git.basschouten.com Git - openhab-addons.git/blob
18870310a2fa0cf6871576071963d5895e2d093f
[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.ecobee.internal.discovery;
14
15 import static org.openhab.binding.ecobee.internal.EcobeeBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.concurrent.Future;
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.ecobee.internal.dto.thermostat.RemoteSensorDTO;
27 import org.openhab.binding.ecobee.internal.dto.thermostat.ThermostatDTO;
28 import org.openhab.binding.ecobee.internal.handler.EcobeeAccountBridgeHandler;
29 import org.openhab.binding.ecobee.internal.handler.EcobeeThermostatBridgeHandler;
30 import org.openhab.core.config.discovery.AbstractDiscoveryService;
31 import org.openhab.core.config.discovery.DiscoveryResult;
32 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingTypeUID;
36 import org.openhab.core.thing.ThingUID;
37 import org.openhab.core.thing.binding.ThingHandler;
38 import org.openhab.core.thing.binding.ThingHandlerService;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * The {@link EcobeeDiscoveryService} is responsible for discovering the Ecobee
44  * thermostats that are associated with the Ecobee Account, as well as the sensors
45  * are associated with the Ecobee thermostats.
46  *
47  * @author Mark Hilbush - Initial contribution
48  */
49 @NonNullByDefault
50 public class EcobeeDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
51
52     private final Logger logger = LoggerFactory.getLogger(EcobeeDiscoveryService.class);
53
54     private @NonNullByDefault({}) EcobeeAccountBridgeHandler bridgeHandler;
55
56     private @Nullable Future<?> discoveryJob;
57
58     public EcobeeDiscoveryService() {
59         super(SUPPORTED_THERMOSTAT_AND_SENSOR_THING_TYPES_UIDS, 8, true);
60     }
61
62     @Override
63     public void setThingHandler(@Nullable ThingHandler handler) {
64         if (handler instanceof EcobeeAccountBridgeHandler) {
65             this.bridgeHandler = (EcobeeAccountBridgeHandler) handler;
66         }
67     }
68
69     @Override
70     public @Nullable ThingHandler getThingHandler() {
71         return bridgeHandler;
72     }
73
74     @Override
75     public void activate() {
76         super.activate(null);
77     }
78
79     @Override
80     public void deactivate() {
81         super.deactivate();
82     }
83
84     @Override
85     public Set<ThingTypeUID> getSupportedThingTypes() {
86         return SUPPORTED_THERMOSTAT_AND_SENSOR_THING_TYPES_UIDS;
87     }
88
89     @Override
90     protected void startBackgroundDiscovery() {
91         logger.debug("EcobeeDiscovery: Starting background discovery job");
92         Future<?> localDiscoveryJob = discoveryJob;
93         if (localDiscoveryJob == null || localDiscoveryJob.isCancelled()) {
94             discoveryJob = scheduler.scheduleWithFixedDelay(this::backgroundDiscover, DISCOVERY_INITIAL_DELAY_SECONDS,
95                     DISCOVERY_INTERVAL_SECONDS, TimeUnit.SECONDS);
96         }
97     }
98
99     @Override
100     protected void stopBackgroundDiscovery() {
101         logger.debug("EcobeeDiscovery: Stopping background discovery job");
102         Future<?> localDiscoveryJob = discoveryJob;
103         if (localDiscoveryJob != null) {
104             localDiscoveryJob.cancel(true);
105             discoveryJob = null;
106         }
107     }
108
109     @Override
110     public void startScan() {
111         logger.debug("EcobeeDiscovery: Starting discovery scan");
112         discover();
113     }
114
115     private void backgroundDiscover() {
116         if (!bridgeHandler.isBackgroundDiscoveryEnabled()) {
117             return;
118         }
119         discover();
120     }
121
122     private void discover() {
123         if (bridgeHandler.getThing().getStatus() != ThingStatus.ONLINE) {
124             logger.debug("EcobeeDiscovery: Skipping discovery because Account Bridge thing is not ONLINE");
125             return;
126         }
127         logger.debug("EcobeeDiscovery: Discovering Ecobee devices");
128         discoverThermostats();
129         discoverSensors();
130     }
131
132     private synchronized void discoverThermostats() {
133         logger.debug("EcobeeDiscovery: Discovering thermostats");
134         for (ThermostatDTO thermostat : bridgeHandler.getRegisteredThermostats()) {
135             String name = thermostat.name;
136             String identifier = thermostat.identifier;
137             if (identifier != null && name != null) {
138                 ThingUID thingUID = new ThingUID(UID_THERMOSTAT_BRIDGE, bridgeHandler.getThing().getUID(), identifier);
139                 thingDiscovered(createThermostatDiscoveryResult(thingUID, identifier, name));
140                 logger.debug("EcobeeDiscovery: Thermostat '{}' and name '{}' added with UID '{}'", identifier, name,
141                         thingUID);
142             }
143         }
144     }
145
146     private DiscoveryResult createThermostatDiscoveryResult(ThingUID thermostatUID, String identifier, String name) {
147         Map<String, Object> properties = new HashMap<>();
148         properties.put(CONFIG_THERMOSTAT_ID, identifier);
149         return DiscoveryResultBuilder.create(thermostatUID).withProperties(properties)
150                 .withRepresentationProperty(CONFIG_THERMOSTAT_ID).withBridge(bridgeHandler.getThing().getUID())
151                 .withLabel(String.format("Ecobee Thermostat %s", name)).build();
152     }
153
154     private synchronized void discoverSensors() {
155         List<Thing> thermostatThings = bridgeHandler.getThing().getThings();
156         if (thermostatThings.isEmpty()) {
157             logger.debug("EcobeeDiscovery: Skipping sensor discovery because there are no thermostat things");
158             return;
159         }
160         logger.debug("EcobeeDiscovery: Discovering sensors");
161         for (Thing thermostat : thermostatThings) {
162             EcobeeThermostatBridgeHandler thermostatHandler = (EcobeeThermostatBridgeHandler) thermostat.getHandler();
163             if (thermostatHandler != null) {
164                 String thermostatId = thermostatHandler.getThermostatId();
165                 logger.debug("EcobeeDiscovery: Discovering sensors for thermostat '{}'", thermostatId);
166                 for (RemoteSensorDTO sensor : thermostatHandler.getSensors()) {
167                     ThingUID bridgeUID = thermostatHandler.getThing().getUID();
168                     ThingUID sensorUID = new ThingUID(UID_SENSOR_THING, bridgeUID, sensor.id.replace(":", "-"));
169                     thingDiscovered(createSensorDiscoveryResult(sensorUID, bridgeUID, sensor));
170                     logger.debug("EcobeeDiscovery: Sensor for '{}' with id '{}' and name '{}' added with UID '{}'",
171                             thermostatId, sensor.id, sensor.name, sensorUID);
172                 }
173             }
174         }
175     }
176
177     private DiscoveryResult createSensorDiscoveryResult(ThingUID sensorUID, ThingUID bridgeUID,
178             RemoteSensorDTO sensor) {
179         Map<String, Object> properties = new HashMap<>();
180         properties.put(CONFIG_SENSOR_ID, sensor.id);
181         return DiscoveryResultBuilder.create(sensorUID).withProperties(properties)
182                 .withRepresentationProperty(CONFIG_SENSOR_ID).withBridge(bridgeUID)
183                 .withLabel(String.format("Ecobee Sensor %s", sensor.name)).build();
184     }
185 }