]> git.basschouten.com Git - openhab-addons.git/blob
89ed78b3059d26a7141629a1e86e9228e6837ebb
[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.siemensrds.internal;
14
15 import static org.openhab.binding.siemensrds.internal.RdsBindingConstants.*;
16
17 import java.io.IOException;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Set;
21 import java.util.concurrent.ScheduledFuture;
22 import java.util.concurrent.TimeUnit;
23 import java.util.stream.Collectors;
24 import java.util.stream.Stream;
25
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;
38
39 import com.google.gson.JsonParseException;
40
41 /**
42  * Discovery service for Siemens RDS thermostats
43  *
44  * @author Andrew Fiddian-Green - Initial contribution
45  * 
46  */
47 @NonNullByDefault
48 public class RdsDiscoveryService extends AbstractDiscoveryService {
49
50     private final Logger logger = LoggerFactory.getLogger(RdsDiscoveryService.class);
51
52     private @Nullable ScheduledFuture<?> discoveryScheduler;
53
54     private @Nullable RdsCloudHandler cloud;
55
56     public static final Set<ThingTypeUID> DISCOVERABLE_THING_TYPES_UIDS = Collections
57             .unmodifiableSet(Stream.of(THING_TYPE_RDS).collect(Collectors.toSet()));
58
59     public RdsDiscoveryService(RdsCloudHandler cloud) {
60         // note: background discovery is enabled in the super method..
61         super(DISCOVERABLE_THING_TYPES_UIDS, DISCOVERY_TIMEOUT);
62         this.cloud = cloud;
63     }
64
65     public void activate() {
66         super.activate(null);
67     }
68
69     @Override
70     public void deactivate() {
71         super.deactivate();
72     }
73
74     @Override
75     protected void startScan() {
76         RdsCloudHandler cloud = this.cloud;
77
78         if (cloud != null && cloud.getThing().getStatus() != ThingStatus.ONLINE) {
79             try {
80                 cloud.getToken();
81             } catch (RdsCloudException e) {
82                 logger.debug("unexpected: {} = \"{}\"", e.getClass().getName(), e.getMessage());
83             }
84         }
85
86         if (cloud != null && cloud.getThing().getStatus() == ThingStatus.ONLINE) {
87             discoverPlants();
88         }
89     }
90
91     @Override
92     protected void startBackgroundDiscovery() {
93         logger.debug("start background discovery..");
94
95         ScheduledFuture<?> discoveryScheduler = this.discoveryScheduler;
96         if (discoveryScheduler == null || discoveryScheduler.isCancelled()) {
97             this.discoveryScheduler = scheduler.scheduleWithFixedDelay(this::startScan, 10, DISCOVERY_REFRESH_PERIOD,
98                     TimeUnit.SECONDS);
99         }
100     }
101
102     @Override
103     protected void stopBackgroundDiscovery() {
104         logger.debug("stop background discovery..");
105
106         ScheduledFuture<?> discoveryScheduler = this.discoveryScheduler;
107         if (discoveryScheduler != null && !discoveryScheduler.isCancelled()) {
108             discoveryScheduler.cancel(true);
109             this.discoveryScheduler = null;
110         }
111     }
112
113     private void discoverPlants() {
114         RdsCloudHandler cloud = this.cloud;
115
116         if (cloud != null) {
117             @Nullable
118             RdsPlants plantClass = null;
119
120             try {
121                 String url = URL_PLANTS;
122
123                 logger.debug(LOG_HTTP_COMMAND, HTTP_GET, url.length());
124                 logger.debug(LOG_PAYLOAD_FMT, LOG_SENDING_MARK, url);
125
126                 String json = RdsDataPoints.httpGenericGetJson(cloud.getApiKey(), cloud.getToken(), url);
127
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)));
135                 }
136
137                 plantClass = RdsPlants.createFromJson(json);
138             } catch (RdsCloudException e) {
139                 logger.warn(LOG_SYSTEM_EXCEPTION, "discoverPlants()", e.getClass().getName(), e.getMessage());
140                 return;
141             } catch (JsonParseException | IOException e) {
142                 logger.warn(LOG_RUNTIME_EXCEPTION, "discoverPlants()", e.getClass().getName(), e.getMessage());
143                 return;
144             }
145
146             if (plantClass != null) {
147                 List<PlantInfo> plants = plantClass.getPlants();
148                 if (plants != null) {
149                     for (PlantInfo plant : plants) {
150                         publishPlant(plant);
151                     }
152                 }
153             }
154         }
155     }
156
157     private void publishPlant(PlantInfo plant) {
158         RdsCloudHandler cloud = this.cloud;
159         try {
160             if (cloud == null) {
161                 throw new RdsCloudException("missing cloud handler");
162             }
163
164             String plantId = plant.getId();
165             String url = String.format(URL_POINTS, plantId);
166
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)));
173             }
174
175             String json = RdsDataPoints.httpGenericGetJson(cloud.getApiKey(), cloud.getToken(), url);
176
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)));
183             }
184
185             RdsDataPoints points = RdsDataPoints.createFromJson(json);
186             if (points == null) {
187                 throw new RdsCloudException("no points returned");
188             }
189
190             State desc = points.getPointByClass(HIE_DESCRIPTION).getState();
191             String label = desc.toString().replaceAll("\\s+", "_");
192
193             ThingTypeUID typeUID = THING_TYPE_RDS;
194             ThingUID bridgeUID = cloud.getThing().getUID();
195             ThingUID plantUID = new ThingUID(typeUID, bridgeUID, plantId);
196
197             DiscoveryResult disco = DiscoveryResultBuilder.create(plantUID).withBridge(bridgeUID).withLabel(label)
198                     .withProperty(PROP_PLANT_ID, plantId).withRepresentationProperty(PROP_PLANT_ID).build();
199
200             logger.debug("discovered typeUID={}, plantUID={}, brigeUID={}, label={}, plantId={}, ", typeUID, plantUID,
201                     bridgeUID, label, plantId);
202
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());
208         }
209     }
210 }