2 * Copyright (c) 2010-2021 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.touchwand.internal;
15 import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.*;
17 import java.io.UnsupportedEncodingException;
18 import java.net.CookieManager;
19 import java.net.MalformedURLException;
21 import java.net.URLEncoder;
22 import java.nio.charset.StandardCharsets;
23 import java.util.HashMap;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.TimeoutException;
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.eclipse.jetty.client.HttpClient;
31 import org.eclipse.jetty.client.api.ContentProvider;
32 import org.eclipse.jetty.client.api.ContentResponse;
33 import org.eclipse.jetty.client.api.Request;
34 import org.eclipse.jetty.client.util.StringContentProvider;
35 import org.eclipse.jetty.http.HttpMethod;
36 import org.eclipse.jetty.http.MimeTypes;
37 import org.openhab.core.library.types.OnOffType;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link TouchWandRestClient} is responsible for handling low level commands units TouchWand WonderFull hub
45 * @author Roie Geron - Initial contribution
48 public class TouchWandRestClient {
50 private final Logger logger = LoggerFactory.getLogger(TouchWandRestClient.class);
52 static CookieManager cookieManager = new CookieManager();
54 private static final HttpMethod METHOD_GET = HttpMethod.GET;
55 private static final HttpMethod METHOD_POST = HttpMethod.POST;
57 private static final String CMD_LOGIN = "login";
58 private static final String CMD_LIST_UNITS = "listunits";
59 private static final String CMD_LIST_SCENARIOS = "listsencarios";
60 private static final String CMD_UNIT_ACTION = "action";
61 private static final String CMD_GET_UNIT_BY_ID = "getunitbyid";
63 private static final String ACTION_SWITCH_OFF = "{\"id\":%s,\"value\":" + SWITCH_STATUS_OFF + "}";
64 private static final String ACTION_SWITCH_ON = "{\"id\":%s,\"value\":" + SWITCH_STATUS_ON + "}";
65 private static final String ACTION_SHUTTER_DOWN = "{\"id\":%s,\"value\":0,\"type\":\"height\"}";
66 private static final String ACTION_SHUTTER_UP = "{\"id\":%s,\"value\":255,\"type\":\"height\"}";
67 private static final String ACTION_SHUTTER_STOP = "{\"id\":%s,\"value\":0,\"type\":\"stop\"}";
68 private static final String ACTION_SHUTTER_POSITION = "{\"id\":%s,\"value\":%s}";
69 private static final String ACTION_DIMMER_POSITION = "{\"id\":%s,\"value\":%s}";
70 private static final String ACTION_THERMOSTAT_ON = "{\"id\":%s,\"value\":" + THERMOSTAT_STATE_ON + "}";
71 private static final String ACTION_THERMOSTAT_OFF = "{\"id\":%s,\"value\":" + THERMOSTAT_STATE_OFF + "}";
72 private static final String ACTION_THERMOSTAT_MODE = "{\"id\":%s,\"ac-all\":\"mode\",\"fan\":\"%s\"}";
73 private static final String ACTION_THERMOSTAT_FAN_LEVEL = "{\"id\":%s,\"ac-all\":\"fan\",\"fan\":\"%s\"}";
74 private static final String ACTION_THERMOSTAT_TARGET_TEMPERATURE = "{\"id\":%s,\"ac-all\":\"temp\",\"temp_val\":%s}";
76 private static final String CONTENT_TYPE_APPLICATION_JSON = MimeTypes.Type.APPLICATION_JSON.asString();
78 private static final int REQUEST_TIMEOUT_SEC = 10;
80 private static final Map<String, String> COMMAND_MAP = new HashMap<String, String>();
82 COMMAND_MAP.put(CMD_LOGIN, "/auth/login?");
83 COMMAND_MAP.put(CMD_LIST_UNITS, "/units/listUnits");
84 COMMAND_MAP.put(CMD_LIST_SCENARIOS, "/scenarios/listScenarios");
85 COMMAND_MAP.put(CMD_UNIT_ACTION, "/units/action");
86 COMMAND_MAP.put(CMD_GET_UNIT_BY_ID, "/units/getUnitByID?");
89 private String touchWandIpAddr = "";
90 private String touchWandPort = "";
91 private boolean isConnected = false;
92 private HttpClient httpClient;
94 public TouchWandRestClient(HttpClient httpClient) {
95 this.httpClient = httpClient;
98 public final boolean connect(String user, String pass, String ipAddr, String port) {
99 touchWandIpAddr = ipAddr;
100 touchWandPort = port;
101 isConnected = cmdLogin(user, pass, ipAddr);
106 private final boolean cmdLogin(String user, String pass, String ipAddr) {
109 String response = "";
112 encodedUser = URLEncoder.encode(user, StandardCharsets.UTF_8.toString());
113 encodedPass = URLEncoder.encode(pass, StandardCharsets.UTF_8.toString());
114 String command = buildUrl(CMD_LOGIN) + "user=" + encodedUser + "&" + "psw=" + encodedPass;
115 response = sendCommand(command, METHOD_GET, "");
116 } catch (UnsupportedEncodingException e) {
117 logger.warn("Error url encoding username or password : {}", e.getMessage());
120 return !response.equals("Unauthorized");
123 public String cmdListUnits() {
124 String response = "";
126 String command = buildUrl(CMD_LIST_UNITS);
127 response = sendCommand(command, METHOD_GET, "");
132 public String cmdGetUnitById(String id) {
133 String response = "";
136 String command = buildUrl(CMD_GET_UNIT_BY_ID) + "id=" + id;
137 response = sendCommand(command, METHOD_GET, "");
142 public void cmdSwitchOnOff(String id, OnOffType onoff) {
145 if (OnOffType.OFF.equals(onoff)) {
146 action = String.format(ACTION_SWITCH_OFF, id);
148 action = String.format(ACTION_SWITCH_ON, id);
150 cmdUnitAction(action);
153 public void cmdShutterUp(String id) {
154 String action = String.format(ACTION_SHUTTER_UP, id);
155 cmdUnitAction(action);
158 public void cmdShutterDown(String id) {
159 String action = String.format(ACTION_SHUTTER_DOWN, id);
160 cmdUnitAction(action);
163 public void cmdShutterPosition(String id, String position) {
164 String action = String.format(ACTION_SHUTTER_POSITION, id, position);
165 cmdUnitAction(action);
168 public void cmdShutterStop(String id) {
169 String action = String.format(ACTION_SHUTTER_STOP, id);
170 cmdUnitAction(action);
173 public void cmdDimmerPosition(String id, String position) {
174 String action = String.format(ACTION_DIMMER_POSITION, id, position);
175 cmdUnitAction(action);
178 public void cmdThermostatOnOff(String id, OnOffType onoff) {
181 if (OnOffType.OFF.equals(onoff)) {
182 action = String.format(ACTION_THERMOSTAT_OFF, id);
184 action = String.format(ACTION_THERMOSTAT_ON, id);
186 cmdUnitAction(action);
189 public void cmdThermostatMode(String id, String mode) {
190 String action = String.format(ACTION_THERMOSTAT_MODE, id, mode);
191 cmdUnitAction(action);
194 public void cmdThermostatFanLevel(String id, String fanLevel) {
195 String action = String.format(ACTION_THERMOSTAT_FAN_LEVEL, id, fanLevel);
196 cmdUnitAction(action);
199 public void cmdThermostatTargetTemperature(String id, String targetTemperature) {
200 String action = String.format(ACTION_THERMOSTAT_TARGET_TEMPERATURE, id, targetTemperature);
201 cmdUnitAction(action);
204 private String cmdUnitAction(String action) {
205 String response = "";
207 String command = buildUrl(CMD_UNIT_ACTION);
208 response = sendCommand(command, METHOD_POST, action);
213 private String buildUrl(String command) {
214 String url = "http://" + touchWandIpAddr + ":" + touchWandPort + COMMAND_MAP.get(command);
218 private synchronized String sendCommand(String command, HttpMethod method, String content) {
219 ContentResponse response;
224 url = new URL(command);
225 } catch (MalformedURLException e) {
226 logger.warn("Error building URL {} : {}", command, e.getMessage());
230 request = httpClient.newRequest(url.toString()).timeout(REQUEST_TIMEOUT_SEC, TimeUnit.SECONDS).method(method);
231 if (method.equals(METHOD_POST) && (!content.isEmpty())) {
232 ContentProvider contentProvider = new StringContentProvider(CONTENT_TYPE_APPLICATION_JSON, content,
233 StandardCharsets.UTF_8);
234 request = request.content(contentProvider);
238 response = request.send();
239 return response.getContentAsString();
240 } catch (InterruptedException | TimeoutException | ExecutionException e) {
241 logger.warn("Error opening connecton to {} : {} ", touchWandIpAddr, e.getMessage());