]> git.basschouten.com Git - openhab-addons.git/blob
f02fe9ea671f34318ef23dbcf9687c6755a43e00
[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
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.core.thing.Bridge;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.ThingStatus;
24 import org.openhab.core.thing.ThingStatusDetail;
25 import org.openhab.core.thing.binding.BaseBridgeHandler;
26 import org.openhab.core.types.Command;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 import com.google.gson.JsonParseException;
31
32 /**
33  * The {@link RdsCloudHandler} is the handler for Siemens RDS cloud account (
34  * also known as the Climatix IC server account )
35  *
36  * @author Andrew Fiddian-Green - Initial contribution
37  *
38  */
39 @NonNullByDefault
40 public class RdsCloudHandler extends BaseBridgeHandler {
41
42     private final Logger logger = LoggerFactory.getLogger(RdsCloudHandler.class);
43
44     private @Nullable RdsCloudConfiguration config = null;
45
46     private @Nullable RdsAccessToken accessToken = null;
47
48     public RdsCloudHandler(Bridge bridge) {
49         super(bridge);
50     }
51
52     @Override
53     public void handleCommand(ChannelUID channelUID, Command command) {
54         // there is nothing to do
55     }
56
57     @Override
58     public void initialize() {
59         RdsCloudConfiguration config = this.config = getConfigAs(RdsCloudConfiguration.class);
60
61         if (config.userEmail.isEmpty()) {
62             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "missing email address");
63             return;
64         }
65
66         if (config.userPassword.isEmpty()) {
67             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "missing password");
68             return;
69         }
70
71         if (logger.isDebugEnabled()) {
72             logger.debug("polling interval={}", config.pollingInterval);
73         }
74
75         if (config.pollingInterval < FAST_POLL_INTERVAL || config.pollingInterval > LAZY_POLL_INTERVAL) {
76             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
77                     String.format("polling interval out of range [%d..%d]", FAST_POLL_INTERVAL, LAZY_POLL_INTERVAL));
78             return;
79         }
80     }
81
82     @Override
83     public void dispose() {
84         // there is nothing to do
85     }
86
87     /*
88      * public method: used by RDS smart thermostat handlers return the polling
89      * interval (seconds)
90      */
91     public int getPollInterval() throws RdsCloudException {
92         RdsCloudConfiguration config = this.config;
93         if (config != null) {
94             return config.pollingInterval;
95         }
96         throw new RdsCloudException("missing polling interval");
97     }
98
99     /*
100      * private method: check if the current token is valid, and renew it if
101      * necessary
102      */
103     private synchronized void refreshToken() {
104         RdsCloudConfiguration config = this.config;
105         RdsAccessToken accessToken = this.accessToken;
106
107         if (accessToken == null || accessToken.isExpired()) {
108             try {
109                 if (config == null) {
110                     throw new RdsCloudException("missing configuration");
111                 }
112
113                 String url = URL_TOKEN;
114                 String payload = String.format(TOKEN_REQUEST, config.userEmail, config.userPassword);
115
116                 logger.debug(LOG_HTTP_COMMAND, HTTP_POST, url.length());
117                 logger.debug(LOG_PAYLOAD_FMT, LOG_SENDING_MARK, url);
118                 logger.debug(LOG_PAYLOAD_FMT, LOG_SENDING_MARK, payload);
119
120                 String json = RdsAccessToken.httpGetTokenJson(config.apiKey, payload);
121
122                 if (logger.isTraceEnabled()) {
123                     logger.trace(LOG_CONTENT_LENGTH, LOG_RECEIVED_MSG, json.length());
124                     logger.trace(LOG_PAYLOAD_FMT, LOG_RECEIVED_MARK, json);
125                 } else if (logger.isDebugEnabled()) {
126                     logger.debug(LOG_CONTENT_LENGTH_ABR, LOG_RECEIVED_MSG, json.length());
127                     logger.debug(LOG_PAYLOAD_FMT_ABR, LOG_RECEIVED_MARK,
128                             json.substring(0, Math.min(json.length(), 30)));
129                 }
130
131                 accessToken = this.accessToken = RdsAccessToken.createFromJson(json);
132             } catch (RdsCloudException e) {
133                 logger.warn(LOG_SYSTEM_EXCEPTION, "refreshToken()", e.getClass().getName(), e.getMessage());
134             } catch (JsonParseException | IOException e) {
135                 logger.warn(LOG_RUNTIME_EXCEPTION, "refreshToken()", e.getClass().getName(), e.getMessage());
136             }
137         }
138
139         if (accessToken != null) {
140             if (getThing().getStatus() != ThingStatus.ONLINE) {
141                 updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, "cloud server responded");
142             }
143         } else {
144             if (getThing().getStatus() == ThingStatus.ONLINE) {
145                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
146                         "cloud server authentication error");
147             }
148         }
149     }
150
151     /*
152      * public method: used by RDS smart thermostat handlers to fetch the current
153      * token
154      */
155     public synchronized String getToken() throws RdsCloudException {
156         refreshToken();
157         RdsAccessToken accessToken = this.accessToken;
158         if (accessToken != null) {
159             return accessToken.getToken();
160         }
161         throw new RdsCloudException("no access token");
162     }
163
164     public String getApiKey() throws RdsCloudException {
165         RdsCloudConfiguration config = this.config;
166         if (config != null) {
167             return config.apiKey;
168         }
169         throw new RdsCloudException("no api key");
170     }
171 }