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