]> git.basschouten.com Git - openhab-addons.git/blob
f159881ec4a22a6010a047e9bf6eebaa60b7a4e8
[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.asuswrt.internal.api;
14
15 import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
16 import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
17 import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.getValueOrDefault;
18
19 import java.net.NoRouteToHostException;
20 import java.util.concurrent.TimeoutException;
21
22 import javax.net.ssl.SSLException;
23 import javax.net.ssl.SSLHandshakeException;
24 import javax.net.ssl.SSLKeyException;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jetty.client.api.ContentResponse;
28 import org.openhab.binding.asuswrt.internal.structures.AsuswrtConfiguration;
29 import org.openhab.binding.asuswrt.internal.structures.AsuswrtCredentials;
30 import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.google.gson.JsonObject;
37
38 /**
39  * The {@link AsuswrtConnector} is a {@link AsuswrtHttpClient} that also keeps track of router configuration and
40  * credentials.
41  *
42  * @author Christian Wild - Initial contribution
43  */
44 @NonNullByDefault
45 public class AsuswrtConnector extends AsuswrtHttpClient {
46     private final Logger logger = LoggerFactory.getLogger(AsuswrtConnector.class);
47     private AsuswrtCredentials credentials;
48     private AsuswrtConfiguration routerConfig;
49     protected Long lastQuery = 0L;
50
51     public AsuswrtConnector(AsuswrtRouter router) {
52         super(router);
53         routerConfig = router.getConfiguration();
54         this.credentials = new AsuswrtCredentials(routerConfig);
55     }
56
57     /*
58      * Connector commands
59      */
60
61     /**
62      * Login to the router.
63      */
64     public Boolean login() {
65         String url = getURL("login.cgi");
66         String encodedCredentials = credentials.getEncodedCredentials();
67         String payload = "";
68
69         logout(); // logout (unset cookie) first
70         router.errorHandler.reset();
71
72         logger.trace("({}) perform login to '{}' with '{}'", uid, url, encodedCredentials);
73
74         payload = "login_authorization=" + encodedCredentials + "}";
75         ContentResponse response = getSyncRequest(url, payload);
76         if (response != null) {
77             setCookieFromResponse(response);
78         }
79         if (cookieStore.isValid()) {
80             router.setState(ThingStatus.ONLINE);
81             return true;
82         }
83         return false;
84     }
85
86     /**
87      * Logout and unsets the cookie.
88      */
89     public void logout() {
90         this.cookieStore.resetCookie();
91     }
92
93     /**
94      * Gets system information from the device.
95      */
96     public void querySysInfo(boolean asyncRequest) {
97         queryDeviceData(CMD_GET_SYSINFO, asyncRequest);
98     }
99
100     /**
101      * Queries data from the device.
102      *
103      * @param command command constant to sent
104      * @param asyncRequest <code>true</code> if request should be sent asynchronous, <code>false</code> if synchronous
105      */
106     public void queryDeviceData(String command, boolean asyncRequest) {
107         logger.trace("({}) queryDeviceData", uid);
108         Long now = System.currentTimeMillis();
109
110         router.errorHandler.reset();
111         if (cookieStore.cookieIsExpired()) {
112             login();
113         }
114
115         if (now > this.lastQuery + HTTP_QUERY_MIN_GAP_MS) {
116             String url = getURL("appGet.cgi");
117             String payload = "hook=" + command;
118             this.lastQuery = now;
119
120             // Send payload as url parameter
121             url = url + "?" + payload;
122             url = url.replace(";", "%3B");
123
124             // Send asynchronous or synchronous HTTP request
125             if (asyncRequest) {
126                 sendAsyncRequest(url, payload, command);
127             } else {
128                 sendSyncRequest(url, payload, command);
129             }
130         } else {
131             logger.trace("({}) query skipped cause of min_gap: {} <- {}", uid, now, lastQuery);
132         }
133     }
134
135     /*
136      * Response handling
137      */
138
139     /**
140      * Handle successful HTTP response by delegating to the connector class.
141      *
142      * @param responseBody response body as string
143      * @param command command constant which was sent
144      */
145     @Override
146     protected void handleHttpSuccessResponse(String responseBody, String command) {
147         JsonObject jsonObject = getJsonFromString(responseBody);
148         router.dataReceived(jsonObject, command);
149     }
150
151     /**
152      * Handles HTTP result failures.
153      *
154      * @param e Throwable exception
155      * @param payload full payload for debugging
156      */
157     @Override
158     protected void handleHttpResultError(Throwable e, String payload) {
159         super.handleHttpResultError(e, payload);
160         String errorMessage = getValueOrDefault(e.getMessage(), "");
161
162         if (e instanceof TimeoutException || e instanceof NoRouteToHostException) {
163             router.errorHandler.raiseError(ERR_CONN_TIMEOUT, errorMessage);
164             router.setState(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
165         } else if (e instanceof SSLException || e instanceof SSLKeyException || e instanceof SSLHandshakeException) {
166             router.errorHandler.raiseError(ERR_SSL_EXCEPTION, payload);
167             router.setState(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
168         } else if (e instanceof InterruptedException) {
169             router.errorHandler.raiseError(new Exception(e), payload);
170             router.setState(ThingStatus.UNKNOWN, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
171         } else {
172             router.errorHandler.raiseError(new Exception(e), errorMessage);
173             router.setState(ThingStatus.UNKNOWN, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
174         }
175     }
176
177     /*
178      * Other
179      */
180
181     /**
182      * Gets the target URL.
183      */
184     protected String getURL(String site) {
185         String url = routerConfig.hostname;
186         if (routerConfig.useSSL) {
187             url = HTTPS_PROTOCOL + url;
188             if (routerConfig.httpsPort != 443) {
189                 url = url + ":" + routerConfig.httpsPort;
190             }
191         } else {
192             url = HTTP_PROTOCOL + url;
193             if (routerConfig.httpPort != 80) {
194                 url = url + ":" + routerConfig.httpPort;
195             }
196         }
197         return url + "/" + site;
198     }
199 }