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.siemensrds.internal;
15 import static org.openhab.binding.siemensrds.internal.RdsBindingConstants.*;
17 import java.io.IOException;
18 import java.util.Collections;
19 import java.util.List;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
23 import java.util.stream.Collectors;
24 import java.util.stream.Stream;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.siemensrds.internal.RdsPlants.PlantInfo;
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.thing.ThingStatus;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.types.State;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.gson.JsonParseException;
42 * Discovery service for Siemens RDS thermostats
44 * @author Andrew Fiddian-Green - Initial contribution
48 public class RdsDiscoveryService extends AbstractDiscoveryService {
50 private final Logger logger = LoggerFactory.getLogger(RdsDiscoveryService.class);
52 private @Nullable ScheduledFuture<?> discoveryScheduler;
54 private @Nullable RdsCloudHandler cloud;
56 public static final Set<ThingTypeUID> DISCOVERABLE_THING_TYPES_UIDS = Collections
57 .unmodifiableSet(Stream.of(THING_TYPE_RDS).collect(Collectors.toSet()));
59 public RdsDiscoveryService(RdsCloudHandler cloud) {
60 // note: background discovery is enabled in the super method..
61 super(DISCOVERABLE_THING_TYPES_UIDS, DISCOVERY_TIMEOUT);
65 public void activate() {
70 public void deactivate() {
75 protected void startScan() {
76 RdsCloudHandler cloud = this.cloud;
78 if (cloud != null && cloud.getThing().getStatus() != ThingStatus.ONLINE) {
81 } catch (RdsCloudException e) {
82 logger.debug("unexpected: {} = \"{}\"", e.getClass().getName(), e.getMessage());
86 if (cloud != null && cloud.getThing().getStatus() == ThingStatus.ONLINE) {
92 protected void startBackgroundDiscovery() {
93 logger.debug("start background discovery..");
95 ScheduledFuture<?> discoveryScheduler = this.discoveryScheduler;
96 if (discoveryScheduler == null || discoveryScheduler.isCancelled()) {
97 this.discoveryScheduler = scheduler.scheduleWithFixedDelay(this::startScan, 10, DISCOVERY_REFRESH_PERIOD,
103 protected void stopBackgroundDiscovery() {
104 logger.debug("stop background discovery..");
106 ScheduledFuture<?> discoveryScheduler = this.discoveryScheduler;
107 if (discoveryScheduler != null && !discoveryScheduler.isCancelled()) {
108 discoveryScheduler.cancel(true);
109 this.discoveryScheduler = null;
113 private void discoverPlants() {
114 RdsCloudHandler cloud = this.cloud;
118 RdsPlants plantClass = null;
121 String url = URL_PLANTS;
123 logger.debug(LOG_HTTP_COMMAND, HTTP_GET, url.length());
124 logger.debug(LOG_PAYLOAD_FMT, LOG_SENDING_MARK, url);
126 String json = RdsDataPoints.httpGenericGetJson(cloud.getApiKey(), cloud.getToken(), url);
128 if (logger.isTraceEnabled()) {
129 logger.trace(LOG_CONTENT_LENGTH, LOG_RECEIVED_MSG, json.length());
130 logger.trace(LOG_PAYLOAD_FMT, LOG_RECEIVED_MARK, json);
131 } else if (logger.isDebugEnabled()) {
132 logger.debug(LOG_CONTENT_LENGTH_ABR, LOG_RECEIVED_MSG, json.length());
133 logger.debug(LOG_PAYLOAD_FMT_ABR, LOG_RECEIVED_MARK,
134 json.substring(0, Math.min(json.length(), 30)));
137 plantClass = RdsPlants.createFromJson(json);
138 } catch (RdsCloudException e) {
139 logger.warn(LOG_SYSTEM_EXCEPTION, "discoverPlants()", e.getClass().getName(), e.getMessage());
141 } catch (JsonParseException | IOException e) {
142 logger.warn(LOG_RUNTIME_EXCEPTION, "discoverPlants()", e.getClass().getName(), e.getMessage());
146 if (plantClass != null) {
147 List<PlantInfo> plants = plantClass.getPlants();
148 if (plants != null) {
149 for (PlantInfo plant : plants) {
157 private void publishPlant(PlantInfo plant) {
158 RdsCloudHandler cloud = this.cloud;
161 throw new RdsCloudException("missing cloud handler");
164 String plantId = plant.getId();
165 String url = String.format(URL_POINTS, plantId);
167 if (logger.isTraceEnabled()) {
168 logger.trace(LOG_HTTP_COMMAND, HTTP_GET, url.length());
169 logger.trace(LOG_PAYLOAD_FMT, LOG_SENDING_MARK, url);
170 } else if (logger.isDebugEnabled()) {
171 logger.debug(LOG_HTTP_COMMAND_ABR, HTTP_GET, url.length());
172 logger.debug(LOG_PAYLOAD_FMT_ABR, LOG_SENDING_MARK, url.substring(0, Math.min(url.length(), 30)));
175 String json = RdsDataPoints.httpGenericGetJson(cloud.getApiKey(), cloud.getToken(), url);
177 if (logger.isTraceEnabled()) {
178 logger.trace(LOG_CONTENT_LENGTH, LOG_RECEIVED_MSG, json.length());
179 logger.trace(LOG_PAYLOAD_FMT, LOG_RECEIVED_MARK, json);
180 } else if (logger.isDebugEnabled()) {
181 logger.debug(LOG_CONTENT_LENGTH_ABR, LOG_RECEIVED_MSG, json.length());
182 logger.debug(LOG_PAYLOAD_FMT_ABR, LOG_RECEIVED_MARK, json.substring(0, Math.min(json.length(), 30)));
185 RdsDataPoints points = RdsDataPoints.createFromJson(json);
186 if (points == null) {
187 throw new RdsCloudException("no points returned");
190 State desc = points.getPointByClass(HIE_DESCRIPTION).getState();
191 String label = desc.toString().replaceAll("\\s+", "_");
193 ThingTypeUID typeUID = THING_TYPE_RDS;
194 ThingUID bridgeUID = cloud.getThing().getUID();
195 ThingUID plantUID = new ThingUID(typeUID, bridgeUID, plantId);
197 DiscoveryResult disco = DiscoveryResultBuilder.create(plantUID).withBridge(bridgeUID).withLabel(label)
198 .withProperty(PROP_PLANT_ID, plantId).withRepresentationProperty(PROP_PLANT_ID).build();
200 logger.debug("discovered typeUID={}, plantUID={}, brigeUID={}, label={}, plantId={}, ", typeUID, plantUID,
201 bridgeUID, label, plantId);
203 thingDiscovered(disco);
204 } catch (RdsCloudException e) {
205 logger.warn(LOG_SYSTEM_EXCEPTION, "publishPlant()", e.getClass().getName(), e.getMessage());
206 } catch (JsonParseException | IOException e) {
207 logger.warn(LOG_RUNTIME_EXCEPTION, "publishPlant()", e.getClass().getName(), e.getMessage());