]> git.basschouten.com Git - openhab-addons.git/blob
20b8c1528909e2aebd9fcad0db50b1dbf7929ef4
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.senechome.internal;
14
15 import java.io.IOException;
16 import java.util.Objects;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jetty.client.HttpClient;
23 import org.eclipse.jetty.client.api.ContentResponse;
24 import org.eclipse.jetty.client.api.Request;
25 import org.eclipse.jetty.client.util.StringContentProvider;
26 import org.eclipse.jetty.http.HttpHeader;
27 import org.eclipse.jetty.http.HttpMethod;
28 import org.eclipse.jetty.http.HttpStatus;
29 import org.eclipse.jetty.http.MimeTypes;
30 import org.openhab.binding.senechome.internal.dto.SenecHomeResponse;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.gson.Gson;
35 import com.google.gson.JsonSyntaxException;
36
37 /**
38  * The {@link SenecHomeApi} class configures http client and
39  * performs status requests
40  *
41  * @author Steven Schwarznau - Initial contribution
42  * @author Robert Delbrück - Update for Senec API changes
43  * @author Lukas Pindl - Update for writing to safeChargeMode
44  *
45  */
46 @NonNullByDefault
47 public class SenecHomeApi {
48     private final Logger logger = LoggerFactory.getLogger(SenecHomeApi.class);
49     private final HttpClient httpClient;
50     private final Gson gson = new Gson();
51     private String hostname = "";
52
53     public SenecHomeApi(HttpClient httpClient) {
54         this.httpClient = httpClient;
55     }
56
57     public void setHostname(String hostname) {
58         this.hostname = hostname;
59     }
60
61     /**
62      * POST json with empty, but expected fields, to lala.cgi of Senec webinterface
63      * the response will contain the same fields, but with the corresponding values
64      *
65      * To receive new values, just modify the Json objects and add them to the thing channels
66      *
67      * @return Instance of SenecHomeResponse
68      * @throws TimeoutException Communication failed (Timeout)
69      * @throws ExecutionException Communication failed
70      * @throws IOException Communication failed
71      * @throws InterruptedException Communication failed (Interrupted)
72      * @throws JsonSyntaxException Received response has an invalid json syntax
73      */
74     public SenecHomeResponse getStatistics()
75             throws TimeoutException, ExecutionException, IOException, InterruptedException, JsonSyntaxException {
76
77         String dataToSend = gson.toJson(new SenecHomeResponse());
78         ContentResponse response = postRequest(dataToSend);
79         return Objects.requireNonNull(gson.fromJson(response.getContentAsString(), SenecHomeResponse.class));
80     }
81
82     /**
83      * POST json, to lala.cgi of Senec webinterface to set a given parameter
84      *
85      * @return boolean, wether or not the request was successful
86      */
87     public boolean setValue(String section, String id, String value) {
88         String dataToSend = "{\"" + section + "\":{\"" + id + "\":\"" + value + "\"}}";
89         try {
90             postRequest(dataToSend);
91             return true;
92         } catch (TimeoutException | ExecutionException | IOException | InterruptedException e) {
93             return false;
94         }
95     }
96
97     /**
98      * helper function to handle the actual POST request to the webinterface
99      *
100      * @return object of type ContentResponse, the response received to the POST request
101      * @throws TimeoutException Communication failed (Timeout)
102      * @throws ExecutionException Communication failed
103      * @throws IOException Communication failed
104      * @throws InterruptedException Communication failed (Interrupted)
105      */
106     private ContentResponse postRequest(String dataToSend)
107             throws TimeoutException, ExecutionException, IOException, InterruptedException {
108         String location = hostname + "/lala.cgi";
109         logger.trace("sending request to: {}", location);
110
111         Request request = httpClient.newRequest(location);
112         request.header(HttpHeader.ACCEPT, MimeTypes.Type.APPLICATION_JSON.asString());
113         request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString());
114         ContentResponse response = null;
115         try {
116             logger.trace("data to send: {}", dataToSend);
117             response = request.method(HttpMethod.POST).content(new StringContentProvider(dataToSend))
118                     .timeout(15, TimeUnit.SECONDS).send();
119             if (response.getStatus() == HttpStatus.OK_200) {
120                 return response;
121             } else {
122                 logger.trace("Got unexpected response code {}", response.getStatus());
123                 throw new IOException("Got unexpected response code " + response.getStatus());
124             }
125         } catch (JsonSyntaxException | InterruptedException | TimeoutException | ExecutionException e) {
126             String errorMessage = "\nlocation: " + location;
127             errorMessage += "\nrequest: " + request.toString();
128             errorMessage += "\nrequest.getHeaders: " + request.getHeaders();
129             if (response == null) {
130                 errorMessage += "\nresponse: null";
131             } else {
132                 errorMessage += "\nresponse: " + response.toString();
133                 errorMessage += "\nresponse.getHeaders: " + response.getHeaders();
134                 if (response.getContent() == null) {
135                     errorMessage += "\nresponse.getContent is null";
136                 } else {
137                     errorMessage += "\nresponse.getContentAsString: " + response.getContentAsString();
138                 }
139             }
140             logger.trace("Issue with getting SenecHomeResponse\n{}", errorMessage);
141             throw e;
142         }
143     }
144 }