]> git.basschouten.com Git - openhab-addons.git/blob
c7280a6d2a0a4b9d3a51b4699dc6faa027f0169f
[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.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
51     private @NonNullByDefault({}) String authToken;
52     private int refreshInterval;
53     private long tokenExpiryDate;
54
55     public AccountHandler(Bridge bridge) {
56         super(bridge);
57     }
58
59     @Override
60     public void handleCommand(ChannelUID channelUID, Command command) {
61         // Nothing to handle here currently
62     }
63
64     @Override
65     public void initialize() {
66         logger.debug("Initialize Pixometer Accountservice");
67
68         PixometerAccountConfiguration config = getConfigAs(PixometerAccountConfiguration.class);
69         setRefreshInterval(config.refresh);
70         String user = config.user;
71         String password = config.password;
72         String scope = "read"; // Prepared for config value
73
74         // Check expiry date every Day and obtain new access token if difference is less then or equal to 2 days
75         scheduler.scheduleWithFixedDelay(() -> {
76             logger.debug("Checking if new access token is needed...");
77             try {
78                 long difference = getTokenExpiryDate() - System.nanoTime();
79                 if (difference <= TOKEN_MIN_DIFF_MS) {
80                     obtainAuthTokenAndExpiryDate(user, password, scope);
81                 }
82             } catch (RuntimeException r) {
83                 logger.debug("Could not check token expiry date for Thing {}: {}", getThing().getUID(), r.getMessage(),
84                         r);
85             }
86         }, 1, TimeUnit.DAYS.toMinutes(1), TimeUnit.MINUTES);
87
88         logger.debug("Refresh job scheduled to run every days. for '{}'", getThing().getUID());
89     }
90
91     @Override
92     public void updateStatus(ThingStatus status) {
93         super.updateStatus(status);
94     }
95
96     /**
97      * Request auth token with read or write access.
98      * (Write access is prepared for a possible later usage for updating meters.)
99      *
100      * @param user The username to use
101      * @param password The corresponding password
102      * @param scope The granted scope on the api for the binding
103      */
104     private void obtainAuthTokenAndExpiryDate(String user, String password, String scope) {
105         try {
106             String url = API_BASE_URL + "v1/access-token/";
107             Properties urlHeader = (Properties) new Properties().put("CONTENT-TYPE", "application/json");
108
109             JsonObject httpBody = new JsonObject();
110             httpBody.addProperty("username", user);
111             httpBody.addProperty("password", password);
112             httpBody.addProperty("scope", scope);
113
114             InputStream content = new ByteArrayInputStream(httpBody.toString().getBytes(StandardCharsets.UTF_8));
115             String urlResponse = HttpUtil.executeUrl("POST", url, urlHeader, content, "application/json", 2000);
116             JsonObject responseJson = (JsonObject) JsonParser.parseString(urlResponse);
117
118             if (responseJson.has(AUTH_TOKEN)) {
119                 // Store the expire date for automatic token refresh
120                 int expiresIn = Integer.parseInt(responseJson.get("expires_in").toString());
121                 setTokenExpiryDate(TimeUnit.SECONDS.toNanos(expiresIn));
122
123                 setAuthToken(responseJson.get(AUTH_TOKEN).toString().replaceAll("\"", ""));
124
125                 updateStatus(ThingStatus.ONLINE);
126                 return;
127             }
128
129             String errorMsg = String.format("Invalid Api Response ( %s )", responseJson);
130
131             throw new IOException(errorMsg);
132         } catch (IOException e) {
133             String errorMsg = String.format(
134                     "Could not obtain auth token. Please check your configured account credentials. %s %s",
135                     this.getThing().getUID(), e.getMessage());
136
137             logger.debug(errorMsg, e);
138             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMsg);
139         }
140     }
141
142     /**
143      * Getters and Setters
144      */
145
146     public String getAuthToken() {
147         return authToken;
148     }
149
150     private void setAuthToken(String authToken) {
151         this.authToken = authToken;
152     }
153
154     public int getRefreshInterval() {
155         return refreshInterval;
156     }
157
158     private void setRefreshInterval(int refreshInterval) {
159         this.refreshInterval = refreshInterval;
160     }
161
162     public long getTokenExpiryDate() {
163         return tokenExpiryDate;
164     }
165
166     private void setTokenExpiryDate(long expiresIn) {
167         this.tokenExpiryDate = System.nanoTime() + expiresIn;
168     }
169 }