]> git.basschouten.com Git - openhab-addons.git/blob
5f9c4a1cf44cc8e58605cbf2ca4330a994b5ae19
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.pixometer.handler;
14
15 import static org.openhab.binding.pixometer.internal.PixometerBindingConstants.*;
16
17 import java.io.ByteArrayInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.nio.charset.StandardCharsets;
21 import java.util.Properties;
22 import java.util.concurrent.TimeUnit;
23
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.openhab.binding.pixometer.internal.config.PixometerAccountConfiguration;
26 import org.openhab.core.io.net.http.HttpUtil;
27 import org.openhab.core.thing.Bridge;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.thing.binding.BaseBridgeHandler;
32 import org.openhab.core.types.Command;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.gson.JsonObject;
37 import com.google.gson.JsonParser;
38
39 /**
40  * The {@link AccountHandler} is responsible for handling the api connection and authorization (including token
41  * refresh)
42  *
43  * @author Jerome Luckenbach - Initial contribution
44  */
45 @NonNullByDefault
46 public class AccountHandler extends BaseBridgeHandler {
47
48     private final Logger logger = LoggerFactory.getLogger(this.getClass());
49     private static final int TOKEN_MIN_DIFF_MS = (int) TimeUnit.DAYS.toMillis(2);
50     private final JsonParser jsonParser = new JsonParser();
51
52     private @NonNullByDefault({}) String authToken;
53     private int refreshInterval;
54     private long tokenExpiryDate;
55
56     public AccountHandler(Bridge bridge) {
57         super(bridge);
58     }
59
60     @Override
61     public void handleCommand(ChannelUID channelUID, Command command) {
62         // Nothing to handle here currently
63     }
64
65     @Override
66     public void initialize() {
67         logger.debug("Initialize Pixometer Accountservice");
68
69         PixometerAccountConfiguration config = getConfigAs(PixometerAccountConfiguration.class);
70         setRefreshInterval(config.refresh);
71         String user = config.user;
72         String password = config.password;
73         String scope = "read"; // Prepared for config value
74
75         // Check expiry date every Day and obtain new access token if difference is less then or equal to 2 days
76         scheduler.scheduleWithFixedDelay(() -> {
77             logger.debug("Checking if new access token is needed...");
78             try {
79                 long difference = getTokenExpiryDate() - System.nanoTime();
80                 if (difference <= TOKEN_MIN_DIFF_MS) {
81                     obtainAuthTokenAndExpiryDate(user, password, scope);
82                 }
83             } catch (RuntimeException r) {
84                 logger.debug("Could not check token expiry date for Thing {}: {}", getThing().getUID(), r.getMessage(),
85                         r);
86             }
87         }, 1, TimeUnit.DAYS.toMinutes(1), TimeUnit.MINUTES);
88
89         logger.debug("Refresh job scheduled to run every days. for '{}'", getThing().getUID());
90     }
91
92     @Override
93     public void updateStatus(ThingStatus status) {
94         super.updateStatus(status);
95     }
96
97     /**
98      * Request auth token with read or write access.
99      * (Write access is prepared for a possible later usage for updating meters.)
100      *
101      * @param user The username to use
102      * @param password The corresponding password
103      * @param scope The granted scope on the api for the binding
104      */
105     private void obtainAuthTokenAndExpiryDate(String user, String password, String scope) {
106         try {
107             String url = API_BASE_URL + "v1/access-token/";
108             Properties urlHeader = (Properties) new Properties().put("CONTENT-TYPE", "application/json");
109
110             JsonObject httpBody = new JsonObject();
111             httpBody.addProperty("username", user);
112             httpBody.addProperty("password", password);
113             httpBody.addProperty("scope", scope);
114
115             InputStream content = new ByteArrayInputStream(httpBody.toString().getBytes(StandardCharsets.UTF_8));
116             String urlResponse = HttpUtil.executeUrl("POST", url, urlHeader, content, "application/json", 2000);
117             JsonObject responseJson = (JsonObject) jsonParser.parse(urlResponse);
118
119             if (responseJson.has(AUTH_TOKEN)) {
120                 // Store the expire date for automatic token refresh
121                 int expiresIn = Integer.parseInt(responseJson.get("expires_in").toString());
122                 setTokenExpiryDate(TimeUnit.SECONDS.toNanos(expiresIn));
123
124                 setAuthToken(responseJson.get(AUTH_TOKEN).toString().replaceAll("\"", ""));
125
126                 updateStatus(ThingStatus.ONLINE);
127                 return;
128             }
129
130             String errorMsg = String.format("Invalid Api Response ( %s )", responseJson);
131
132             throw new IOException(errorMsg);
133         } catch (IOException e) {
134             String errorMsg = String.format(
135                     "Could not obtain auth token. Please check your configured account credentials. %s %s",
136                     this.getThing().getUID(), e.getMessage());
137
138             logger.debug(errorMsg, e);
139             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMsg);
140         }
141     }
142
143     /**
144      * Getters and Setters
145      */
146
147     public String getAuthToken() {
148         return authToken;
149     }
150
151     private void setAuthToken(String authToken) {
152         this.authToken = authToken;
153     }
154
155     public int getRefreshInterval() {
156         return refreshInterval;
157     }
158
159     private void setRefreshInterval(int refreshInterval) {
160         this.refreshInterval = refreshInterval;
161     }
162
163     public long getTokenExpiryDate() {
164         return tokenExpiryDate;
165     }
166
167     private void setTokenExpiryDate(long expiresIn) {
168         this.tokenExpiryDate = System.nanoTime() + expiresIn;
169     }
170 }