]> git.basschouten.com Git - openhab-addons.git/blob
049f0cae45d005545954373e565590114c200b87
[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.miele.internal;
14
15 import java.io.StringReader;
16 import java.net.URI;
17 import java.net.URISyntaxException;
18 import java.util.Random;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeoutException;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.client.util.StringContentProvider;
27 import org.eclipse.jetty.http.HttpMethod;
28 import org.openhab.binding.miele.internal.exceptions.MieleRpcException;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.gson.Gson;
33 import com.google.gson.JsonArray;
34 import com.google.gson.JsonElement;
35 import com.google.gson.JsonObject;
36 import com.google.gson.JsonParseException;
37 import com.google.gson.JsonParser;
38
39 /**
40  * The {@link MieleGatewayCommunicationController} class is used for communicating with
41  * the XGW 3000 gateway through JSON-RPC.
42  *
43  * @author Jacob Laursen - Initial contribution
44  */
45 @NonNullByDefault
46 public class MieleGatewayCommunicationController {
47
48     private final URI uri;
49     private final Random rand = new Random();
50     private final Gson gson = new Gson();
51     private final Logger logger = LoggerFactory.getLogger(MieleGatewayCommunicationController.class);
52     private final HttpClient httpClient;
53
54     public MieleGatewayCommunicationController(HttpClient httpClient, String host) throws URISyntaxException {
55         uri = new URI("http://" + host + "/remote/json-rpc");
56         this.httpClient = httpClient;
57     }
58
59     public JsonElement invokeOperation(FullyQualifiedApplianceIdentifier applianceIdentifier, String modelID,
60             String methodName) throws MieleRpcException {
61         Object[] args = new Object[4];
62         args[0] = applianceIdentifier.getUid();
63         args[1] = MieleBindingConstants.MIELE_CLASS + modelID;
64         args[2] = methodName;
65         args[3] = null;
66
67         return invokeRPC("HDAccess/invokeDCOOperation", args);
68     }
69
70     public JsonElement invokeRPC(String methodName, Object[] args) throws MieleRpcException {
71         JsonElement result = null;
72         JsonObject requestBodyAsJson = new JsonObject();
73         int id = rand.nextInt(Integer.MAX_VALUE);
74         requestBodyAsJson.addProperty("jsonrpc", "2.0");
75         requestBodyAsJson.addProperty("id", id);
76         requestBodyAsJson.addProperty("method", methodName);
77
78         JsonArray params = new JsonArray();
79         for (Object o : args) {
80             params.add(gson.toJsonTree(o));
81         }
82         requestBodyAsJson.add("params", params);
83
84         String requestBody = requestBodyAsJson.toString();
85         Request request = httpClient.newRequest(uri).method(HttpMethod.POST)
86                 .content(new StringContentProvider(requestBody), "application/json");
87
88         String responseData = null;
89         try {
90             final ContentResponse contentResponse = request.send();
91             final int httpStatus = contentResponse.getStatus();
92             if (httpStatus != 200) {
93                 if (httpStatus == 503) {
94                     throw new MieleRpcException("Gateway is temporarily unavailable");
95                 }
96                 throw new MieleRpcException("Unexpected HTTP status code " + httpStatus);
97             }
98             responseData = contentResponse.getContentAsString();
99         } catch (TimeoutException e) {
100             throw new MieleRpcException("Timeout when calling gateway", e);
101         } catch (ExecutionException e) {
102             throw new MieleRpcException("Failure when calling gateway", e);
103         } catch (InterruptedException e) {
104             Thread.currentThread().interrupt();
105             throw new MieleRpcException("Interrupted while calling gateway", e);
106         }
107
108         logger.trace("The request '{}' yields '{}'", requestBody, responseData);
109         JsonObject parsedResponse = null;
110         try {
111             parsedResponse = (JsonObject) JsonParser.parseReader(new StringReader(responseData));
112         } catch (JsonParseException e) {
113             throw new MieleRpcException("Error parsing JSON response", e);
114         }
115
116         JsonElement error = parsedResponse.get("error");
117         if (error != null && !error.isJsonNull()) {
118             if (error.isJsonPrimitive()) {
119                 throw new MieleRpcException("Remote exception occurred: '" + error.getAsString() + "'");
120             } else if (error.isJsonObject()) {
121                 JsonObject o = error.getAsJsonObject();
122                 Integer code = (o.has("code") ? o.get("code").getAsInt() : null);
123                 String message = (o.has("message") ? o.get("message").getAsString() : null);
124                 String data = (o.has("data")
125                         ? (o.get("data") instanceof JsonObject ? o.get("data").toString() : o.get("data").getAsString())
126                         : "");
127                 throw new MieleRpcException(
128                         "Remote exception occurred: '" + code + "':'" + message + "':'" + data + "'");
129             } else {
130                 throw new MieleRpcException("Unknown remote exception occurred: '" + error.toString() + "'");
131             }
132         }
133
134         result = parsedResponse.get("result");
135         if (result == null) {
136             throw new MieleRpcException("Result is missing in response");
137         }
138
139         return result;
140     }
141 }