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.hydrawise.internal.api;
16 import java.util.Objects;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jetty.client.HttpClient;
23 import org.eclipse.jetty.client.api.AuthenticationStore;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.eclipse.jetty.client.util.BasicAuthentication;
26 import org.eclipse.jetty.http.HttpMethod;
27 import org.openhab.binding.hydrawise.internal.api.model.LocalScheduleResponse;
28 import org.openhab.binding.hydrawise.internal.api.model.SetZoneResponse;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 import com.google.gson.FieldNamingPolicy;
33 import com.google.gson.Gson;
34 import com.google.gson.GsonBuilder;
37 * The {@link HydrawiseLocalApiClient} communicates with a network local Hydrawise controller.
39 * @author Dan Cunningham - Initial contribution
42 public class HydrawiseLocalApiClient {
43 private final Logger logger = LoggerFactory.getLogger(HydrawiseLocalApiClient.class);
45 private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
48 private static final String GET_LOCAL_DATA_URL = "%s/get_sched_json.php?hours=720";
49 private static final String SET_LOCAL_DATA_URL = "%s/set_manual_data.php?period_id=998";
51 private static final int TIMEOUT_SECONDS = 30;
52 private HttpClient httpClient;
53 private String localSetURL = "";
54 private String localGetURL = "";
56 public HydrawiseLocalApiClient(HttpClient httpClient) {
57 this.httpClient = httpClient;
61 * Initializes the {@link HydrawiseLocalApiClient} to talk with the network local Hydrawise API
67 public HydrawiseLocalApiClient(String host, String username, String password, HttpClient httpClient) {
68 this.httpClient = httpClient;
69 setCredentials(host, username, password);
73 * Sets the local credentials and controller host
79 public void setCredentials(String host, String username, String password) {
80 String url = "http://" + host;
81 localSetURL = String.format(SET_LOCAL_DATA_URL, url);
82 localGetURL = String.format(GET_LOCAL_DATA_URL, url);
83 AuthenticationStore auth = httpClient.getAuthenticationStore();
84 URI uri = URI.create(url);
85 auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri, username, password));
89 * Retrieves the {@link LocalScheduleResponse} for the controller
91 * @return the local schedule response
92 * @throws HydrawiseConnectionException
93 * @throws HydrawiseAuthenticationException
95 public LocalScheduleResponse getLocalSchedule()
96 throws HydrawiseConnectionException, HydrawiseAuthenticationException {
97 String json = doGet(localGetURL);
98 LocalScheduleResponse response = gson.fromJson(json, LocalScheduleResponse.class);
99 return Objects.requireNonNull(response);
103 * Stops a given relay
106 * @return Response message
107 * @throws HydrawiseConnectionException
108 * @throws HydrawiseAuthenticationException
109 * @throws HydrawiseCommandException
111 public String stopRelay(int number)
112 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
113 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("stop").relayNumber(number).toString());
117 * Runs a given relay for the default amount of time
120 * @return Response message
121 * @throws HydrawiseConnectionException
122 * @throws HydrawiseAuthenticationException
123 * @throws HydrawiseCommandException
125 public String runRelay(int number)
126 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
127 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("run").relayNumber(number).toString());
131 * Runs a given relay for a specified numbers of seconds
135 * @return Response message
136 * @throws HydrawiseConnectionException
137 * @throws HydrawiseAuthenticationException
138 * @throws HydrawiseCommandException
140 public String runRelay(int seconds, int number)
141 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
142 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("run").relayNumber(number)
143 .duration(seconds).toString());
149 * @return Response message
150 * @throws HydrawiseConnectionException
151 * @throws HydrawiseAuthenticationException
152 * @throws HydrawiseCommandException
154 public String stopAllRelays()
155 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
156 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("stopall").toString());
160 * Run all relays for the default amount of time
162 * @return Response message
163 * @throws HydrawiseConnectionException
164 * @throws HydrawiseAuthenticationException
165 * @throws HydrawiseCommandException
167 public String runAllRelays()
168 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
169 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("runall").toString());
173 * Run all relays for a given amount of seconds
176 * @return Response message
177 * @throws HydrawiseConnectionException
178 * @throws HydrawiseAuthenticationException
179 * @throws HydrawiseCommandException
181 public String runAllRelays(int seconds)
182 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
183 return relayCommand(new HydrawiseZoneCommandBuilder(localSetURL).action("runall").duration(seconds).toString());
186 private String relayCommand(String url)
187 throws HydrawiseConnectionException, HydrawiseAuthenticationException, HydrawiseCommandException {
188 String json = doGet(url);
189 SetZoneResponse response = gson.fromJson(json, SetZoneResponse.class);
190 if (response.messageType.equals("error")) {
191 throw new HydrawiseCommandException(response.message);
193 return response.message;
196 private String doGet(String url) throws HydrawiseConnectionException, HydrawiseAuthenticationException {
197 logger.trace("Getting {}", url);
198 ContentResponse response;
200 response = httpClient.newRequest(url).method(HttpMethod.GET).timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
202 } catch (InterruptedException | TimeoutException | ExecutionException e) {
203 throw new HydrawiseConnectionException(e);
205 if (response.getStatus() == 401) {
206 throw new HydrawiseAuthenticationException();
208 if (response.getStatus() != 200) {
209 throw new HydrawiseConnectionException("Error from controller. Response code " + response.getStatus());
211 String stringResponse = response.getContentAsString();
212 logger.trace("Response: {}", stringResponse);
213 return stringResponse;