2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.asuswrt.internal.api;
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;
19 import java.net.NoRouteToHostException;
20 import java.util.concurrent.TimeoutException;
22 import javax.net.ssl.SSLException;
23 import javax.net.ssl.SSLHandshakeException;
24 import javax.net.ssl.SSLKeyException;
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;
36 import com.google.gson.JsonObject;
39 * The {@link AsuswrtConnector} is a {@link AsuswrtHttpClient} that also keeps track of router configuration and
42 * @author Christian Wild - Initial contribution
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;
51 public AsuswrtConnector(AsuswrtRouter router) {
53 routerConfig = router.getConfiguration();
54 this.credentials = new AsuswrtCredentials(routerConfig);
62 * Login to the router.
64 public Boolean login() {
65 String url = getURL("login.cgi");
66 String encodedCredentials = credentials.getEncodedCredentials();
69 logout(); // logout (unset cookie) first
70 router.errorHandler.reset();
72 logger.trace("({}) perform login to '{}' with '{}'", uid, url, encodedCredentials);
74 payload = "login_authorization=" + encodedCredentials + "}";
75 ContentResponse response = getSyncRequest(url, payload);
76 if (response != null) {
77 setCookieFromResponse(response);
79 if (cookieStore.isValid()) {
80 router.setState(ThingStatus.ONLINE);
87 * Logout and unsets the cookie.
89 public void logout() {
90 this.cookieStore.resetCookie();
94 * Gets system information from the device.
96 public void querySysInfo(boolean asyncRequest) {
97 queryDeviceData(CMD_GET_SYSINFO, asyncRequest);
101 * Queries data from the device.
103 * @param command command constant to sent
104 * @param asyncRequest <code>true</code> if request should be sent asynchronous, <code>false</code> if synchronous
106 public void queryDeviceData(String command, boolean asyncRequest) {
107 logger.trace("({}) queryDeviceData", uid);
108 Long now = System.currentTimeMillis();
110 router.errorHandler.reset();
111 if (cookieStore.cookieIsExpired()) {
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;
120 // Send payload as url parameter
121 url = url + "?" + payload;
122 url = url.replace(";", "%3B");
124 // Send asynchronous or synchronous HTTP request
126 sendAsyncRequest(url, payload, command);
128 sendSyncRequest(url, payload, command);
131 logger.trace("({}) query skipped cause of min_gap: {} <- {}", uid, now, lastQuery);
140 * Handle successful HTTP response by delegating to the connector class.
142 * @param responseBody response body as string
143 * @param command command constant which was sent
146 protected void handleHttpSuccessResponse(String responseBody, String command) {
147 JsonObject jsonObject = getJsonFromString(responseBody);
148 router.dataReceived(jsonObject, command);
152 * Handles HTTP result failures.
154 * @param e Throwable exception
155 * @param payload full payload for debugging
158 protected void handleHttpResultError(Throwable e, String payload) {
159 super.handleHttpResultError(e, payload);
160 String errorMessage = getValueOrDefault(e.getMessage(), "");
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);
172 router.errorHandler.raiseError(new Exception(e), errorMessage);
173 router.setState(ThingStatus.UNKNOWN, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
182 * Gets the target URL.
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;
192 url = HTTP_PROTOCOL + url;
193 if (routerConfig.httpPort != 80) {
194 url = url + ":" + routerConfig.httpPort;
197 return url + "/" + site;