2 * Copyright (c) 2010-2023 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.automower.internal.rest.api.automowerconnect;
15 import java.util.concurrent.ExecutionException;
16 import java.util.concurrent.TimeUnit;
17 import java.util.concurrent.TimeoutException;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jetty.client.HttpClient;
21 import org.eclipse.jetty.client.api.ContentResponse;
22 import org.eclipse.jetty.client.api.Request;
23 import org.eclipse.jetty.client.util.StringContentProvider;
24 import org.eclipse.jetty.http.HttpMethod;
25 import org.eclipse.jetty.http.HttpStatus;
26 import org.openhab.binding.automower.internal.rest.api.HusqvarnaApi;
27 import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerCommandRequest;
28 import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerListResult;
29 import org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerResult;
30 import org.openhab.binding.automower.internal.rest.exceptions.AutomowerCommunicationException;
31 import org.openhab.binding.automower.internal.rest.exceptions.UnauthorizedException;
33 import com.google.gson.JsonSyntaxException;
36 * Allows access to the AutomowerConnectApi
38 * @author Markus Pfleger - Initial contribution
41 public class AutomowerConnectApi extends HusqvarnaApi {
42 public AutomowerConnectApi(HttpClient httpClient) {
47 public String getBaseUrl() {
48 return "https://api.amc.husqvarna.dev/v1";
51 public MowerListResult getMowers(String appKey, String token) throws AutomowerCommunicationException {
52 final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers");
53 request.method(HttpMethod.GET);
55 ContentResponse response = executeRequest(appKey, token, request);
57 return parseResponse(response, MowerListResult.class);
60 public MowerResult getMower(String appKey, String token, String mowerId) throws AutomowerCommunicationException {
61 final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers/" + mowerId);
62 request.method(HttpMethod.GET);
64 ContentResponse response = executeRequest(appKey, token, request);
66 return parseResponse(response, MowerResult.class);
69 public void sendCommand(String appKey, String token, String id, MowerCommandRequest command)
70 throws AutomowerCommunicationException {
71 final Request request = getHttpClient().newRequest(getBaseUrl() + "/mowers/" + id + "/actions");
72 request.method(HttpMethod.POST);
74 request.content(new StringContentProvider(gson.toJson(command)));
76 ContentResponse response = executeRequest(appKey, token, request);
78 checkForError(response, response.getStatus());
81 private ContentResponse executeRequest(String appKey, String token, final Request request)
82 throws AutomowerCommunicationException {
83 request.timeout(10, TimeUnit.SECONDS);
85 request.header("Authorization-Provider", "husqvarna");
86 request.header("Authorization", "Bearer " + token);
87 request.header("X-Api-Key", appKey);
88 request.header("Content-Type", "application/vnd.api+json");
90 ContentResponse response;
92 response = request.send();
93 } catch (TimeoutException | ExecutionException e) {
94 throw new AutomowerCommunicationException(e);
95 } catch (InterruptedException e) {
96 Thread.currentThread().interrupt();
97 throw new AutomowerCommunicationException(e);
102 private <T> T parseResponse(ContentResponse response, Class<T> type) throws AutomowerCommunicationException {
103 int statusCode = response.getStatus();
105 checkForError(response, statusCode);
108 return gson.fromJson(response.getContentAsString(), type);
109 } catch (JsonSyntaxException e) {
110 throw new AutomowerCommunicationException(e);
114 private void checkForError(ContentResponse response, int statusCode) throws AutomowerCommunicationException {
115 if (statusCode >= 200 && statusCode < 300) {
119 switch (statusCode) {
120 case HttpStatus.NOT_FOUND_404:
121 throw new AutomowerCommunicationException(statusCode, "Target '" + response.getRequest().getURI()
122 + "' seems to be not available: " + response.getContentAsString());
124 case HttpStatus.FORBIDDEN_403:
125 case HttpStatus.UNAUTHORIZED_401:
126 throw new UnauthorizedException(statusCode, response.getContentAsString());
129 throw new AutomowerCommunicationException(statusCode, response.getContentAsString());